mirror of
https://github.com/MagicMirrorOrg/MagicMirror.git
synced 2026-01-11 18:47:55 -05:00
Compare commits
4164 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a4fbbf48a | ||
|
|
f7465679c0 | ||
|
|
2a5299ebcb | ||
|
|
b3bddb2c99 | ||
|
|
997aec8cc2 | ||
|
|
c67320f185 | ||
|
|
8224a6ac35 | ||
|
|
abcee8aa56 | ||
|
|
23c6b44921 | ||
|
|
1034171e91 | ||
|
|
bf49f79e6e | ||
|
|
f7f24dbdfe | ||
|
|
31ec848aec | ||
|
|
9eb08420b6 | ||
|
|
eb6d8d4f83 | ||
|
|
e10f620cf9 | ||
|
|
f750436b64 | ||
|
|
a4a8504558 | ||
|
|
385e5aabaa | ||
|
|
d831315e20 | ||
|
|
e0906f3462 | ||
|
|
6595b6a44f | ||
|
|
0183d7a080 | ||
|
|
89e803ee42 | ||
|
|
c0ce52abe3 | ||
|
|
a1c7f20990 | ||
|
|
0ef6f89d44 | ||
|
|
54b04962a8 | ||
|
|
60f8de282d | ||
|
|
b4350278a0 | ||
|
|
c3c5307624 | ||
|
|
879d585f2e | ||
|
|
9969fede35 | ||
|
|
c15b31b374 | ||
|
|
a3a6c33b32 | ||
|
|
236bf6e0fc | ||
|
|
974de179e0 | ||
|
|
60e03777f3 | ||
|
|
05f6b2510f | ||
|
|
f3274977f5 | ||
|
|
cf7fb1a3b9 | ||
|
|
12457a87d4 | ||
|
|
9a8de7db80 | ||
|
|
68e02a528e | ||
|
|
277055f44e | ||
|
|
c3fc745c7e | ||
|
|
8901ed219d | ||
|
|
d7c70dc021 | ||
|
|
53c789bff9 | ||
|
|
eb63745664 | ||
|
|
91d72e48ad | ||
|
|
1dcda63192 | ||
|
|
3ea6544f77 | ||
|
|
d12a587f11 | ||
|
|
2b147bb98b | ||
|
|
6529eaaf9a | ||
|
|
a68aa148b8 | ||
|
|
98942d6f9c | ||
|
|
690efc0aff | ||
|
|
627cfa1dff | ||
|
|
99aca932db | ||
|
|
dd43f35bbe | ||
|
|
093988e136 | ||
|
|
087a472765 | ||
|
|
ce13d7f98b | ||
|
|
b1fc766908 | ||
|
|
22384342db | ||
|
|
badce5146a | ||
|
|
0bf3ff9c17 | ||
|
|
860840c367 | ||
|
|
221b6325f6 | ||
|
|
06389e35f9 | ||
|
|
a7756cec13 | ||
|
|
9ee11654a6 | ||
|
|
a273266e5e | ||
|
|
e2158716d6 | ||
|
|
c132206543 | ||
|
|
f49312ed13 | ||
|
|
a9f69f07e6 | ||
|
|
d7429a4812 | ||
|
|
be76d5ce9a | ||
|
|
f2bc10c5c0 | ||
|
|
43eb760bce | ||
|
|
a7684e3e9f | ||
|
|
8949aa3bec | ||
|
|
e40ddd4b69 | ||
|
|
17637fb1f6 | ||
|
|
f71defe958 | ||
|
|
b8d6a6da1f | ||
|
|
fbc886b21c | ||
|
|
8879fb55de | ||
|
|
ed316e8bf3 | ||
|
|
45529f7de9 | ||
|
|
dbdff38d2e | ||
|
|
21c3179e03 | ||
|
|
c05d93aed8 | ||
|
|
6225abb010 | ||
|
|
c41fff8f5c | ||
|
|
8589d9c482 | ||
|
|
7f264953af | ||
|
|
cfff2ad72b | ||
|
|
c0258b352e | ||
|
|
3e1b051ec3 | ||
|
|
b34bb87d7a | ||
|
|
83b8cc6729 | ||
|
|
878c0be727 | ||
|
|
e7f06f5c0c | ||
|
|
a1fc38c5fe | ||
|
|
ff0ab24000 | ||
|
|
56a10d192d | ||
|
|
1a8413d8f0 | ||
|
|
934b156ebb | ||
|
|
f9639d9705 | ||
|
|
4c345c4f33 | ||
|
|
490151267a | ||
|
|
3d19a08cc7 | ||
|
|
385c4c32f9 | ||
|
|
3a5052c871 | ||
|
|
f84f590f1d | ||
|
|
5b9eba7819 | ||
|
|
cd18794fca | ||
|
|
ae3d552ad7 | ||
|
|
be5f71f4a7 | ||
|
|
745a5f0376 | ||
|
|
99114b2a61 | ||
|
|
df9bd2b0f9 | ||
|
|
e194b559ac | ||
|
|
af5344dccd | ||
|
|
2d7b8121d7 | ||
|
|
0297450702 | ||
|
|
6b17f6aa28 | ||
|
|
8a7abfe42d | ||
|
|
dd5041395c | ||
|
|
36d6a5bc15 | ||
|
|
2619f92d09 | ||
|
|
53720ae8ae | ||
|
|
bcff953fbb | ||
|
|
bcc0cc599d | ||
|
|
a1e3fed312 | ||
|
|
399dca2ef9 | ||
|
|
2e44e1626d | ||
|
|
39aa2dfe01 | ||
|
|
099929c677 | ||
|
|
af5d132410 | ||
|
|
79acbc3a98 | ||
|
|
e75e4e2284 | ||
|
|
9aa0af4f9c | ||
|
|
50e272efba | ||
|
|
209e049893 | ||
|
|
bbb3accf0c | ||
|
|
179989aa42 | ||
|
|
2881d19d43 | ||
|
|
7cfc3458ec | ||
|
|
659e1da79d | ||
|
|
a7ae79493d | ||
|
|
8b484ee707 | ||
|
|
d617d4aa09 | ||
|
|
99c04648b4 | ||
|
|
f945d50c0d | ||
|
|
e9fabd59ed | ||
|
|
ad13de3588 | ||
|
|
aad8141e27 | ||
|
|
26a76f80d6 | ||
|
|
53ead2087f | ||
|
|
faee811d67 | ||
|
|
b9c739df1f | ||
|
|
6e124842e8 | ||
|
|
7a5928ea24 | ||
|
|
7fdf7de11c | ||
|
|
b75eedb84e | ||
|
|
3b92ae49a9 | ||
|
|
775d1091db | ||
|
|
1f77b491fc | ||
|
|
eff2fd7cc0 | ||
|
|
58d2a0d874 | ||
|
|
ea9def997a | ||
|
|
a222c58047 | ||
|
|
39a838c2ab | ||
|
|
cfc0bcd5ad | ||
|
|
3418c9b50f | ||
|
|
e686611890 | ||
|
|
ebb5dee1fc | ||
|
|
d9edaffd9c | ||
|
|
cbe7b1a5b9 | ||
|
|
e758fd4093 | ||
|
|
14a99a3b25 | ||
|
|
1ba67506a0 | ||
|
|
2a6ca5d5ac | ||
|
|
aa12e6495a | ||
|
|
9269848f66 | ||
|
|
a71e61cd30 | ||
|
|
8be4604c97 | ||
|
|
a7bba903f5 | ||
|
|
1d8af5835d | ||
|
|
189c01fc74 | ||
|
|
e3a5bbf661 | ||
|
|
ee23c5f72c | ||
|
|
a2083be76b | ||
|
|
a1c4be83d6 | ||
|
|
d2fde2bfc8 | ||
|
|
e8956b0b55 | ||
|
|
2af4009a93 | ||
|
|
a5f7c946cc | ||
|
|
298542b531 | ||
|
|
fca6707a29 | ||
|
|
10d3a284e9 | ||
|
|
1a244726aa | ||
|
|
044935a164 | ||
|
|
99e5edf2c5 | ||
|
|
b26270bd13 | ||
|
|
65a8cb9ddb | ||
|
|
ba4b976e80 | ||
|
|
297ae1dbaf | ||
|
|
214614f740 | ||
|
|
0e14d3d6e8 | ||
|
|
67011c0c32 | ||
|
|
16bbb42b8d | ||
|
|
b85ac91e6c | ||
|
|
66759a33fa | ||
|
|
bf5e83861c | ||
|
|
d56a6fb06f | ||
|
|
5e7aa8e16d | ||
|
|
bace0ad339 | ||
|
|
6014eaf8eb | ||
|
|
3e96e8b3f5 | ||
|
|
95d1b8a6d0 | ||
|
|
0ecb66c99e | ||
|
|
af52b91799 | ||
|
|
3c50d6c30a | ||
|
|
2722c72c43 | ||
|
|
d5ab3101c6 | ||
|
|
32df76bdff | ||
|
|
68a06c3d1d | ||
|
|
1b42dc779b | ||
|
|
cedffd40f2 | ||
|
|
cdc8db4837 | ||
|
|
a0ee23d84e | ||
|
|
49d2d8c9d0 | ||
|
|
63620aa811 | ||
|
|
d5b11a1dba | ||
|
|
4a63af0490 | ||
|
|
a68019293f | ||
|
|
6b1c91f0dd | ||
|
|
ea93785581 | ||
|
|
32819c4fd5 | ||
|
|
fc5a438cdc | ||
|
|
57fe94f945 | ||
|
|
aa3a3bdf16 | ||
|
|
db89da3daa | ||
|
|
d6ba5796ce | ||
|
|
3968743b28 | ||
|
|
20c6226b84 | ||
|
|
463ce394fe | ||
|
|
1faefebe42 | ||
|
|
e2c9339ec4 | ||
|
|
4b1c7da171 | ||
|
|
bdfd6e5e9f | ||
|
|
4c8508b0a9 | ||
|
|
06b3f92963 | ||
|
|
d43a57af36 | ||
|
|
aeefe28710 | ||
|
|
e9de961a23 | ||
|
|
dcec778e02 | ||
|
|
b212641069 | ||
|
|
90aa50bb11 | ||
|
|
a6879e853b | ||
|
|
37fab7ac63 | ||
|
|
8b01ae08c5 | ||
|
|
b1cdf42790 | ||
|
|
974968d238 | ||
|
|
bf467cbba5 | ||
|
|
536aa2e96e | ||
|
|
3d84344b75 | ||
|
|
1054ba3b1e | ||
|
|
aa8ddb9a92 | ||
|
|
fcfe57e5e2 | ||
|
|
c4fd4e0317 | ||
|
|
3c76933824 | ||
|
|
fa83819bee | ||
|
|
b65ae88879 | ||
|
|
96db21f9bf | ||
|
|
6d356ff770 | ||
|
|
21790b32bf | ||
|
|
159f3d0aa2 | ||
|
|
012a7b0678 | ||
|
|
6595c85671 | ||
|
|
cf5c0464fe | ||
|
|
e31450f731 | ||
|
|
3653984a95 | ||
|
|
0c0b856c37 | ||
|
|
69f1b153ea | ||
|
|
43ba4bd00e | ||
|
|
bf5edcaac6 | ||
|
|
ac51709211 | ||
|
|
e1a578e819 | ||
|
|
591c9e53b0 | ||
|
|
87d543eb3a | ||
|
|
40c1521591 | ||
|
|
b31c2a6264 | ||
|
|
66a42f13f1 | ||
|
|
8de6ebbbd1 | ||
|
|
649de694ed | ||
|
|
8a52fde8fc | ||
|
|
fb8bd657de | ||
|
|
b04a0a6b61 | ||
|
|
f29c911a0f | ||
|
|
bd908123c2 | ||
|
|
cbdb0b67ab | ||
|
|
aa3848f420 | ||
|
|
6cf0748172 | ||
|
|
11122d3f81 | ||
|
|
2dea9398f2 | ||
|
|
de93b3294f | ||
|
|
7accb84eb9 | ||
|
|
ea90ed04d6 | ||
|
|
838eed2630 | ||
|
|
376b65c749 | ||
|
|
3b4432cb00 | ||
|
|
7bc71029de | ||
|
|
d736dd92be | ||
|
|
6eba8d681c | ||
|
|
5fe654c19d | ||
|
|
dd366f35a8 | ||
|
|
2ababa521d | ||
|
|
bda8f26511 | ||
|
|
7f1a3df25b | ||
|
|
ef2ff50089 | ||
|
|
0b3964c827 | ||
|
|
ccf5bb9342 | ||
|
|
4303882c6a | ||
|
|
c34028d549 | ||
|
|
8e76cdcb57 | ||
|
|
5eb66106b9 | ||
|
|
0abebc1e32 | ||
|
|
552e82f44d | ||
|
|
ada40e36db | ||
|
|
480f734a06 | ||
|
|
20bee9c334 | ||
|
|
de8267f41e | ||
|
|
7bfaf07980 | ||
|
|
a42fa8e9f9 | ||
|
|
5facad683a | ||
|
|
fd1913a72e | ||
|
|
54c98b4250 | ||
|
|
5d99baac21 | ||
|
|
cb95bdf6d7 | ||
|
|
25e803abfc | ||
|
|
7c6073e4ef | ||
|
|
09bcbe8dfc | ||
|
|
e0a9c7d0bb | ||
|
|
ac27d05fd5 | ||
|
|
d6ab56252f | ||
|
|
dab178ed50 | ||
|
|
6ed50b6a75 | ||
|
|
ee559ec650 | ||
|
|
4310238418 | ||
|
|
10c47a6c38 | ||
|
|
4b8043086e | ||
|
|
fd952b88bf | ||
|
|
e262d463c5 | ||
|
|
b02bce2510 | ||
|
|
58094531c0 | ||
|
|
d937e3ca7c | ||
|
|
9c58413209 | ||
|
|
db65ff12d7 | ||
|
|
f93b819ea6 | ||
|
|
e6fea297e5 | ||
|
|
5c2a0e5634 | ||
|
|
71aa21a82d | ||
|
|
23821360c7 | ||
|
|
79f5b938f5 | ||
|
|
f8769fcc2a | ||
|
|
a3ed24c766 | ||
|
|
82727b825c | ||
|
|
16e98496af | ||
|
|
62896ce1a3 | ||
|
|
7ea5b1ecbf | ||
|
|
eecc95f8fb | ||
|
|
85808d85c4 | ||
|
|
12cc670642 | ||
|
|
13fcb55df6 | ||
|
|
a4dfd15888 | ||
|
|
7fbd326298 | ||
|
|
331d147d50 | ||
|
|
acdcdc55bc | ||
|
|
fdb0c0acb3 | ||
|
|
564bf47fb2 | ||
|
|
eca35b2371 | ||
|
|
f97d2e2644 | ||
|
|
fdd6659139 | ||
|
|
0d698fb659 | ||
|
|
c68b39dda8 | ||
|
|
cb67286bc3 | ||
|
|
a49962b8de | ||
|
|
256d5ae14f | ||
|
|
799ee8bcfa | ||
|
|
fe8a317ef9 | ||
|
|
b6d6ee45e0 | ||
|
|
0151466a28 | ||
|
|
3588875e28 | ||
|
|
e8031aec39 | ||
|
|
1cabe107e6 | ||
|
|
ba0c59744b | ||
|
|
50c702c00a | ||
|
|
ff8c2fe227 | ||
|
|
f9c78a5263 | ||
|
|
d46784a4d5 | ||
|
|
ff43d082f2 | ||
|
|
83801736d7 | ||
|
|
e16986cf71 | ||
|
|
7ad12d954c | ||
|
|
fb74fadec2 | ||
|
|
c00bdf910e | ||
|
|
50cc1c56e5 | ||
|
|
0006099758 | ||
|
|
162dcec331 | ||
|
|
3e8bd022e2 | ||
|
|
01e5936671 | ||
|
|
d85e1c70d6 | ||
|
|
f329770194 | ||
|
|
08194925cb | ||
|
|
2b7aa3e810 | ||
|
|
549417f106 | ||
|
|
f0f370cc7d | ||
|
|
b842241f8c | ||
|
|
93aa4b7440 | ||
|
|
9e2eef7818 | ||
|
|
b29b65851e | ||
|
|
a6829bff4f | ||
|
|
491f5aa776 | ||
|
|
d401e59031 | ||
|
|
63ce69ce82 | ||
|
|
f15972c823 | ||
|
|
b210fcdcf3 | ||
|
|
8ea37a5a45 | ||
|
|
daf98c36fc | ||
|
|
6a0e6eb84e | ||
|
|
7bcdd2a42c | ||
|
|
670a760404 | ||
|
|
a99de1ad13 | ||
|
|
108fe2082d | ||
|
|
e67dc38890 | ||
|
|
20a87656ff | ||
|
|
70c3b68e67 | ||
|
|
bfcb7dc601 | ||
|
|
39e16221fb | ||
|
|
d11e4e5c92 | ||
|
|
cccaa1f33d | ||
|
|
37d3aa25b1 | ||
|
|
ebfe96d31d | ||
|
|
e902b8c52f | ||
|
|
201b36d62c | ||
|
|
7b29070516 | ||
|
|
9ed2e4d557 | ||
|
|
38544f2368 | ||
|
|
df39408411 | ||
|
|
2e01f988f5 | ||
|
|
2b940c9cfb | ||
|
|
b6f4737ecc | ||
|
|
89d6473052 | ||
|
|
99d838f9cd | ||
|
|
f3bdddfaa9 | ||
|
|
87f952c87b | ||
|
|
639305ecc8 | ||
|
|
a70bb517e1 | ||
|
|
e4f671c898 | ||
|
|
a269b5cd93 | ||
|
|
2ec275957f | ||
|
|
4f9fc032e5 | ||
|
|
5c9dbccc10 | ||
|
|
b2cf470ec9 | ||
|
|
bceb181b47 | ||
|
|
1a314b741a | ||
|
|
7635dea3e9 | ||
|
|
90112d1a7d | ||
|
|
ad0cf12e53 | ||
|
|
a53029f11e | ||
|
|
848529f9f4 | ||
|
|
b5dc91fd07 | ||
|
|
0a2b939514 | ||
|
|
52584f36d7 | ||
|
|
30c7a24fc2 | ||
|
|
0643a103ac | ||
|
|
71bd45dfd4 | ||
|
|
85c9d3b331 | ||
|
|
5e6cbeb9ba | ||
|
|
3d4429d418 | ||
|
|
d3d64d3ca0 | ||
|
|
6de983aeb2 | ||
|
|
05c3a5bf83 | ||
|
|
c2f5d038de | ||
|
|
0ac5032db9 | ||
|
|
9b93066cbe | ||
|
|
bc60ae21c4 | ||
|
|
0b37ed072c | ||
|
|
57174f09b9 | ||
|
|
61057d1a25 | ||
|
|
03964d6f68 | ||
|
|
7515fc10d1 | ||
|
|
6583f05858 | ||
|
|
2b1dbbde68 | ||
|
|
49c95a9f46 | ||
|
|
a6214c8da3 | ||
|
|
d2b3414ac6 | ||
|
|
401a6f3417 | ||
|
|
3ed223a550 | ||
|
|
47bd48e0a3 | ||
|
|
cdd1853369 | ||
|
|
8f2980c23d | ||
|
|
b72556b9a9 | ||
|
|
49be3cbd6b | ||
|
|
fbb0c59b4e | ||
|
|
d83e696a8d | ||
|
|
a467d900c9 | ||
|
|
96be8d6fea | ||
|
|
8b1ce26fa6 | ||
|
|
514b9453f8 | ||
|
|
fa0f997928 | ||
|
|
504e7cadd7 | ||
|
|
c80aeff945 | ||
|
|
454206c803 | ||
|
|
e4f47178fc | ||
|
|
1f9109f8e4 | ||
|
|
f09c54184a | ||
|
|
92a35692f2 | ||
|
|
53e300bd31 | ||
|
|
e8be6ad4f1 | ||
|
|
01b9ecb339 | ||
|
|
6ff85ebe54 | ||
|
|
ea6eebd809 | ||
|
|
b2a21b937d | ||
|
|
13010ecaee | ||
|
|
2e2e157017 | ||
|
|
e23e33852e | ||
|
|
5b270b84b4 | ||
|
|
9094240024 | ||
|
|
1db0dbf52b | ||
|
|
beb5faef8b | ||
|
|
c6aff8b7dc | ||
|
|
1aacc37c83 | ||
|
|
b18d98f5ea | ||
|
|
09ddd3d925 | ||
|
|
e2b4823e43 | ||
|
|
04491ac5ac | ||
|
|
e3bee5aae7 | ||
|
|
89152e537e | ||
|
|
652e1a528f | ||
|
|
9d85baee37 | ||
|
|
bdc4ed4d86 | ||
|
|
35f3b315a2 | ||
|
|
efec49bb47 | ||
|
|
68bc77c81e | ||
|
|
dbea348779 | ||
|
|
b46160bcbc | ||
|
|
ddb06ca214 | ||
|
|
ef2fd16b69 | ||
|
|
d874ad9988 | ||
|
|
57dc349675 | ||
|
|
120f0299b2 | ||
|
|
b5b6df5e48 | ||
|
|
5ffd20b843 | ||
|
|
3dacce6675 | ||
|
|
8e4ba4fe93 | ||
|
|
37d488760f | ||
|
|
7cdeceedf1 | ||
|
|
7ba76020d8 | ||
|
|
aab1b97653 | ||
|
|
221eadcc20 | ||
|
|
4a11cdc564 | ||
|
|
b9333134c7 | ||
|
|
8c83dc9494 | ||
|
|
1ed721fb15 | ||
|
|
88ed5ed373 | ||
|
|
84995c9252 | ||
|
|
6fadc76fe3 | ||
|
|
d240986fdc | ||
|
|
afc73920ad | ||
|
|
16615c3da2 | ||
|
|
88c80973f1 | ||
|
|
e322be2624 | ||
|
|
059b87bbb4 | ||
|
|
911675f995 | ||
|
|
e76fe5e25a | ||
|
|
308774c2a6 | ||
|
|
db24f20289 | ||
|
|
94bb8e6c03 | ||
|
|
41da6f455a | ||
|
|
d2a7a3b0bb | ||
|
|
afbdacf136 | ||
|
|
2324579057 | ||
|
|
3c357f057b | ||
|
|
5116a2fc82 | ||
|
|
c0ddc020d5 | ||
|
|
0683734d5a | ||
|
|
6cbd267384 | ||
|
|
925113fa20 | ||
|
|
3696d45e94 | ||
|
|
cb3ae66652 | ||
|
|
948b6c8de8 | ||
|
|
3c4d7a33e0 | ||
|
|
5a421220c9 | ||
|
|
41508931be | ||
|
|
e2cfa24686 | ||
|
|
d48113f2d9 | ||
|
|
16c5bddbb7 | ||
|
|
ef7556f6d3 | ||
|
|
a3cb0b7b96 | ||
|
|
4d28688f30 | ||
|
|
01ff00fa31 | ||
|
|
78190d9c7f | ||
|
|
b1565e4047 | ||
|
|
db220b7861 | ||
|
|
eaf27b837e | ||
|
|
74410344af | ||
|
|
998f64f983 | ||
|
|
684dfb643b | ||
|
|
314c3cb516 | ||
|
|
58939bfd8c | ||
|
|
33592b3c0e | ||
|
|
ad9c2549bc | ||
|
|
5152e0b114 | ||
|
|
ca48663efd | ||
|
|
b520b4c37a | ||
|
|
90f07295b1 | ||
|
|
3895c18466 | ||
|
|
2b6a9fc5bb | ||
|
|
052f0b8709 | ||
|
|
a5bb9d962d | ||
|
|
2d9d28aa0f | ||
|
|
69c053a94f | ||
|
|
aaaf1f660c | ||
|
|
8538d83520 | ||
|
|
132c98b767 | ||
|
|
42cac81953 | ||
|
|
3ee4bd65c6 | ||
|
|
fcc7e80bf9 | ||
|
|
e0d43a4c1e | ||
|
|
4966d6c920 | ||
|
|
1fd506f25d | ||
|
|
a99698d1a9 | ||
|
|
774b86c7dc | ||
|
|
2c3e8533c7 | ||
|
|
3eda8af671 | ||
|
|
aa61874848 | ||
|
|
2deab31187 | ||
|
|
b177a56fa2 | ||
|
|
6f0f75cf27 | ||
|
|
39bb2eb9b0 | ||
|
|
7b36bb025a | ||
|
|
aa9a1b7af2 | ||
|
|
caf3552d6b | ||
|
|
6e9897f7fc | ||
|
|
fa9258761e | ||
|
|
003e948899 | ||
|
|
9cd998f219 | ||
|
|
d75b894d9a | ||
|
|
5a3d3b76a7 | ||
|
|
5bc2c207db | ||
|
|
612cf25878 | ||
|
|
5ae4912b45 | ||
|
|
a9a70fd2e9 | ||
|
|
f90856808b | ||
|
|
7dbcaa83bc | ||
|
|
38f10b6e3e | ||
|
|
9c8fa06ce1 | ||
|
|
4efe04774c | ||
|
|
5d60534dc9 | ||
|
|
ac141a4316 | ||
|
|
d22064c6f4 | ||
|
|
189721ebba | ||
|
|
7aa9c63dba | ||
|
|
16e894e300 | ||
|
|
d466705ec0 | ||
|
|
0e97d863ce | ||
|
|
5de64d2ae8 | ||
|
|
ced0398e49 | ||
|
|
d4b57924a7 | ||
|
|
d2def2bea3 | ||
|
|
e65bb84f9f | ||
|
|
69b0aa6118 | ||
|
|
10dc315f3b | ||
|
|
0f1457b5d7 | ||
|
|
090873d4c2 | ||
|
|
da00c168ae | ||
|
|
8286d5a06e | ||
|
|
dc5fb978a7 | ||
|
|
a4ab0cbe09 | ||
|
|
4a341b381e | ||
|
|
3fa98bc1aa | ||
|
|
87e2e87ce6 | ||
|
|
c25b6dc16c | ||
|
|
6a786aa090 | ||
|
|
a97d87bce8 | ||
|
|
fba91329f1 | ||
|
|
353cc3b00f | ||
|
|
057ef63586 | ||
|
|
c9fb38981e | ||
|
|
9ea7de8b44 | ||
|
|
020c8ccd2a | ||
|
|
4d09abe725 | ||
|
|
5079e30caf | ||
|
|
e51f6597ed | ||
|
|
e80a65a3cd | ||
|
|
3e5c1a278b | ||
|
|
4ded60874f | ||
|
|
7c3675c9e1 | ||
|
|
ff1a843de6 | ||
|
|
e6cefcf948 | ||
|
|
a857412f13 | ||
|
|
e507f95b2a | ||
|
|
61cf92c67a | ||
|
|
7a4eddc592 | ||
|
|
3fcbf15915 | ||
|
|
efafb1c28a | ||
|
|
67bedf8648 | ||
|
|
c1d35b0f91 | ||
|
|
d3a715bd6b | ||
|
|
28b52cd24f | ||
|
|
46e77f805c | ||
|
|
dd23db0ad8 | ||
|
|
30cf7f8afe | ||
|
|
7802e0bb88 | ||
|
|
07e75b8550 | ||
|
|
1e9fad8278 | ||
|
|
0975826457 | ||
|
|
e5ff320591 | ||
|
|
02c1e47749 | ||
|
|
a50824eeee | ||
|
|
0c3f9f4ed9 | ||
|
|
6b12601c6f | ||
|
|
225bece44e | ||
|
|
a5a5e73196 | ||
|
|
f8085ed78f | ||
|
|
4e6e84c637 | ||
|
|
846212798c | ||
|
|
571f95eb2f | ||
|
|
202eeea33f | ||
|
|
af212057db | ||
|
|
0fd0fea7e7 | ||
|
|
eb6ef3c8ff | ||
|
|
cdb8d35cf6 | ||
|
|
684dcdcef3 | ||
|
|
155351f5dd | ||
|
|
0419e06e7c | ||
|
|
2ea38bd9a4 | ||
|
|
30db9c30c8 | ||
|
|
a8ef594dab | ||
|
|
9858d5b495 | ||
|
|
20bd85b676 | ||
|
|
83ec8ca24f | ||
|
|
9622d02230 | ||
|
|
b72d0ed37e | ||
|
|
f966e504a5 | ||
|
|
a0366e794b | ||
|
|
3c3ce24397 | ||
|
|
30290f3eb2 | ||
|
|
616431e04b | ||
|
|
d0aeb90f0a | ||
|
|
86220fa721 | ||
|
|
0f58a56a07 | ||
|
|
29451562e3 | ||
|
|
911687af2a | ||
|
|
1c9c33b87b | ||
|
|
f485462af1 | ||
|
|
39d7ceb017 | ||
|
|
8251792a0d | ||
|
|
54ac450f92 | ||
|
|
299e4a497f | ||
|
|
3f851c1fd6 | ||
|
|
8cf16f1049 | ||
|
|
b373aa6250 | ||
|
|
2f4b8cd642 | ||
|
|
85b6df3738 | ||
|
|
c675421a6a | ||
|
|
a7b571e5d0 | ||
|
|
b3a9b7ef0e | ||
|
|
e984893853 | ||
|
|
3024319027 | ||
|
|
21ba652413 | ||
|
|
e4b8cd92f2 | ||
|
|
1a4a9f6501 | ||
|
|
e950cdaf32 | ||
|
|
f97be2f8f3 | ||
|
|
be0c8f4f16 | ||
|
|
46fd2de315 | ||
|
|
72f0d77865 | ||
|
|
d43679d59e | ||
|
|
ce46fb5384 | ||
|
|
43b33cb6de | ||
|
|
0344399253 | ||
|
|
3a9b154cb2 | ||
|
|
1074fbacfe | ||
|
|
00ff3ab380 | ||
|
|
db874a011c | ||
|
|
35a2839a2f | ||
|
|
cdb9b9bb87 | ||
|
|
87a3e4d440 | ||
|
|
284bed677e | ||
|
|
667be460e5 | ||
|
|
c49386bb58 | ||
|
|
adb50a9623 | ||
|
|
ac1d2372f4 | ||
|
|
f54690c829 | ||
|
|
053f9c34aa | ||
|
|
e7dd2b4aee | ||
|
|
6f82f9e01b | ||
|
|
d531730dc1 | ||
|
|
00bdf6aaa6 | ||
|
|
97f3514677 | ||
|
|
137facf95a | ||
|
|
8afba3a5c4 | ||
|
|
9c5383dc37 | ||
|
|
260bc9664e | ||
|
|
655ca83356 | ||
|
|
472bf1665c | ||
|
|
db129cc19b | ||
|
|
b735f8a524 | ||
|
|
1e34764588 | ||
|
|
99aaae491c | ||
|
|
f288581c69 | ||
|
|
3c5d50bce9 | ||
|
|
a01f08391b | ||
|
|
51a1399bca | ||
|
|
b735cb96a0 | ||
|
|
d00c25e107 | ||
|
|
8a5e87b116 | ||
|
|
2779d19d5c | ||
|
|
38d4a8b198 | ||
|
|
ccf98c0c22 | ||
|
|
bd0d91d1b4 | ||
|
|
056f3a6ccb | ||
|
|
20a50f8382 | ||
|
|
21284e7795 | ||
|
|
e0ceed5a63 | ||
|
|
958a2ee6ec | ||
|
|
ea264cb15e | ||
|
|
d8f19e631c | ||
|
|
ce5c0ed5ba | ||
|
|
839ca9ecfb | ||
|
|
720bc12c00 | ||
|
|
1ba845fb06 | ||
|
|
e86fa9d24a | ||
|
|
e348a61085 | ||
|
|
2f70366299 | ||
|
|
c466b20558 | ||
|
|
021f8d25a5 | ||
|
|
a19c3a43d8 | ||
|
|
819923e66d | ||
|
|
6c3100e250 | ||
|
|
1065eda47f | ||
|
|
afd676a958 | ||
|
|
12405b66d0 | ||
|
|
ecd0b6fa83 | ||
|
|
3a8587378c | ||
|
|
a05c08ed48 | ||
|
|
469a90787b | ||
|
|
9e5a9b5ced | ||
|
|
f311ba3f7c | ||
|
|
fc68321bd5 | ||
|
|
8a4173d0ad | ||
|
|
90af31cb2f | ||
|
|
61bcd9337b | ||
|
|
7944045893 | ||
|
|
2c3f83c70d | ||
|
|
92ab705ff5 | ||
|
|
2951f0c40c | ||
|
|
8a23bccb70 | ||
|
|
aa6ad01fb9 | ||
|
|
ef325896c5 | ||
|
|
a270c73d7c | ||
|
|
16feda895d | ||
|
|
874a50d142 | ||
|
|
ae32645470 | ||
|
|
d4412fe06f | ||
|
|
b42c05fb56 | ||
|
|
8d0da61bd4 | ||
|
|
8b8be261cd | ||
|
|
2b6ceed897 | ||
|
|
8abca801a2 | ||
|
|
1eae4425d8 | ||
|
|
a6386bd60e | ||
|
|
1460f002ab | ||
|
|
0d6f736c2c | ||
|
|
da88e11d04 | ||
|
|
0a58767563 | ||
|
|
198525f2ce | ||
|
|
3220702034 | ||
|
|
262711a127 | ||
|
|
078438442a | ||
|
|
5ac20d65ac | ||
|
|
5d2f706c32 | ||
|
|
844a59d880 | ||
|
|
82c742f964 | ||
|
|
b73cfd8a60 | ||
|
|
8466ff0c1a | ||
|
|
1e0fc7eb0d | ||
|
|
74b0c3ea57 | ||
|
|
a735275864 | ||
|
|
8a1d46deb4 | ||
|
|
b624aeec45 | ||
|
|
e83b4d7d42 | ||
|
|
da302fce32 | ||
|
|
e09fec56e2 | ||
|
|
568f952573 | ||
|
|
fc1e488391 | ||
|
|
5781c258e0 | ||
|
|
13c542aeda | ||
|
|
02148f68e5 | ||
|
|
3c84002abd | ||
|
|
01aa57e493 | ||
|
|
af09b4214a | ||
|
|
43b6c71205 | ||
|
|
480e1adfbf | ||
|
|
8c04712784 | ||
|
|
0c61ba8f2d | ||
|
|
485f662d75 | ||
|
|
26caeec0c1 | ||
|
|
4a7cb88a3e | ||
|
|
d11696015d | ||
|
|
3b76ca4f9b | ||
|
|
6f3239d514 | ||
|
|
e8f60d39de | ||
|
|
a3bad8aec4 | ||
|
|
644aa26b75 | ||
|
|
ecd9828afc | ||
|
|
7462d61e16 | ||
|
|
b95ef7250d | ||
|
|
569dec1b0b | ||
|
|
1bc0270d7b | ||
|
|
ebfeebc40b | ||
|
|
ec80b25087 | ||
|
|
7a2278d7b6 | ||
|
|
28b93b70fa | ||
|
|
0431f45190 | ||
|
|
96ce444061 | ||
|
|
32776e7ca3 | ||
|
|
35d516ad4d | ||
|
|
e6a17d27b9 | ||
|
|
52edec1b64 | ||
|
|
6440d2289c | ||
|
|
11afadcea8 | ||
|
|
2e981987f2 | ||
|
|
69efca0bdb | ||
|
|
eefb92367e | ||
|
|
8fa96c2836 | ||
|
|
04dae52a6c | ||
|
|
37c9da1351 | ||
|
|
86d7ec6270 | ||
|
|
82f1e0fe32 | ||
|
|
6ec0aa8894 | ||
|
|
3dbe8bfbbf | ||
|
|
20d82bab78 | ||
|
|
60f6123b64 | ||
|
|
74887a58f6 | ||
|
|
76821d16fc | ||
|
|
233a6b5e90 | ||
|
|
a1d9337c81 | ||
|
|
e3fec6c3e4 | ||
|
|
5de88b4cc1 | ||
|
|
af5e6655e0 | ||
|
|
a8716799c9 | ||
|
|
1672027091 | ||
|
|
934ac886cb | ||
|
|
1b47c4d16f | ||
|
|
e8fd906aa1 | ||
|
|
57b6ea1297 | ||
|
|
102ff15a99 | ||
|
|
19148cfc84 | ||
|
|
97c2bab58a | ||
|
|
1f473228ce | ||
|
|
340a8e4176 | ||
|
|
67201a52cc | ||
|
|
30e164fe0a | ||
|
|
cfcb20a468 | ||
|
|
24eac7ef41 | ||
|
|
94162f1b45 | ||
|
|
01c19efc0c | ||
|
|
e4f2a8a23b | ||
|
|
89b33d2c62 | ||
|
|
3ced35a2f8 | ||
|
|
fd4576b234 | ||
|
|
812ad829c9 | ||
|
|
207a9ba723 | ||
|
|
f9bf17d701 | ||
|
|
43b96ccd1e | ||
|
|
14e8cdd9b2 | ||
|
|
259068b860 | ||
|
|
a1a4192835 | ||
|
|
45f09dcc8c | ||
|
|
15c3f11f4a | ||
|
|
1a21027850 | ||
|
|
8427a9fc68 | ||
|
|
f09b89f975 | ||
|
|
7bec84f767 | ||
|
|
8f4cbcf817 | ||
|
|
c3382274a2 | ||
|
|
493055f861 | ||
|
|
11fbbd49f3 | ||
|
|
8ce37d53cd | ||
|
|
baa4012872 | ||
|
|
16c5eba2be | ||
|
|
ec08cb32aa | ||
|
|
86fb1b938b | ||
|
|
5aa7097a6e | ||
|
|
fd3f520e95 | ||
|
|
49ff92892f | ||
|
|
904f5a2656 | ||
|
|
bb105dd832 | ||
|
|
fd934c0514 | ||
|
|
66609428a2 | ||
|
|
0056e0bc6d | ||
|
|
056b66a764 | ||
|
|
3438a5a374 | ||
|
|
9f3806dabf | ||
|
|
1d4d5cc4e7 | ||
|
|
3901543697 | ||
|
|
a4d73e2a67 | ||
|
|
f6854f58ff | ||
|
|
ad7f7d2890 | ||
|
|
498db63cac | ||
|
|
05659820d0 | ||
|
|
02779ef725 | ||
|
|
935c9b6a42 | ||
|
|
522f7644a3 | ||
|
|
b1a67d1fc5 | ||
|
|
0674c0aff6 | ||
|
|
c8664d5952 | ||
|
|
8ce1e2c956 | ||
|
|
90cca28e01 | ||
|
|
e489b7101c | ||
|
|
eee64c8064 | ||
|
|
a0d4e8dafc | ||
|
|
e6b94df06d | ||
|
|
6f1c7d6253 | ||
|
|
2d5a19b676 | ||
|
|
d1e8dded68 | ||
|
|
9888f66c84 | ||
|
|
5ec51d0ccc | ||
|
|
79f9331073 | ||
|
|
43bcf4ab98 | ||
|
|
f4eae72c48 | ||
|
|
9d14d3e5b7 | ||
|
|
26d3141489 | ||
|
|
5c44f51d6d | ||
|
|
50f3f32ba8 | ||
|
|
8fa858ca8c | ||
|
|
8b1d1671f7 | ||
|
|
73aa35ea2c | ||
|
|
a391445e5f | ||
|
|
530c5d416a | ||
|
|
319a13c0ef | ||
|
|
ec2fedd797 | ||
|
|
7489d19784 | ||
|
|
3b5a0e8d66 | ||
|
|
29ed63286c | ||
|
|
108da4b6d4 | ||
|
|
a00a1c64d1 | ||
|
|
275825cfe1 | ||
|
|
cd2fce56a6 | ||
|
|
cab850fb35 | ||
|
|
045dc600b0 | ||
|
|
1b199c1682 | ||
|
|
936fa637ec | ||
|
|
b9ccb7a892 | ||
|
|
95b33be3cf | ||
|
|
cde27b89c2 | ||
|
|
476e52e004 | ||
|
|
8dc88fe64b | ||
|
|
d00da790af | ||
|
|
c61fac75e4 | ||
|
|
e949af6fd5 | ||
|
|
c1e38b917e | ||
|
|
1244121216 | ||
|
|
46543daa13 | ||
|
|
6277384bf9 | ||
|
|
17549fed9c | ||
|
|
377e42affc | ||
|
|
0ac5d56865 | ||
|
|
b59ee6ad7e | ||
|
|
2d7c5a827f | ||
|
|
85c32ef843 | ||
|
|
dc089d7db9 | ||
|
|
d570f910f8 | ||
|
|
8f2731911b | ||
|
|
9d22420027 | ||
|
|
029da3791b | ||
|
|
caa51b1029 | ||
|
|
2973a03d40 | ||
|
|
679d464f4c | ||
|
|
93c0787efd | ||
|
|
a1708a1469 | ||
|
|
862bf78e63 | ||
|
|
8c01df50a2 | ||
|
|
921932920d | ||
|
|
d021c9b4ae | ||
|
|
309a18e9c0 | ||
|
|
73322c96a6 | ||
|
|
121e7db330 | ||
|
|
9f5e1b59fb | ||
|
|
3282ed4fea | ||
|
|
c7d9192f18 | ||
|
|
bd0f707aed | ||
|
|
8b30634ebe | ||
|
|
ca8acb14f1 | ||
|
|
26b8f8d0d5 | ||
|
|
a066153556 | ||
|
|
2ee7131c28 | ||
|
|
cb1f65732e | ||
|
|
37237d9c10 | ||
|
|
92cc41dec6 | ||
|
|
246dc663c4 | ||
|
|
4ed3235590 | ||
|
|
0939e405b4 | ||
|
|
584c51ef56 | ||
|
|
26ed05ba3a | ||
|
|
018cb91526 | ||
|
|
e16db2233f | ||
|
|
5d90a08011 | ||
|
|
2d3849a671 | ||
|
|
e0dcdc2110 | ||
|
|
22fcee2a16 | ||
|
|
8c0141367b | ||
|
|
5bb72cfed8 | ||
|
|
6d829fa575 | ||
|
|
85ed1b85ae | ||
|
|
c9d0bd2d7f | ||
|
|
ea31d34649 | ||
|
|
1d2f929d3f | ||
|
|
ffbf0804d9 | ||
|
|
ca0b89ecd3 | ||
|
|
dc9d6f6b79 | ||
|
|
f73520559e | ||
|
|
a4df38d963 | ||
|
|
4a162543f6 | ||
|
|
7a3ea37798 | ||
|
|
fdd389d6b7 | ||
|
|
b91fccc0e3 | ||
|
|
d911b075ab | ||
|
|
4339cdd8a4 | ||
|
|
dd32d3a492 | ||
|
|
d5caadd906 | ||
|
|
c4bc3e2687 | ||
|
|
2c5909a138 | ||
|
|
42c13fa584 | ||
|
|
3b442d4bfc | ||
|
|
9831f81b6e | ||
|
|
d3282506c9 | ||
|
|
2afff6c432 | ||
|
|
be3616abe2 | ||
|
|
daa6f5051c | ||
|
|
1e5bd98f02 | ||
|
|
7e5bfa8dd2 | ||
|
|
53363b0618 | ||
|
|
b2f71a2ce1 | ||
|
|
5d4a575919 | ||
|
|
7d521ed3ce | ||
|
|
bb9ad3daa9 | ||
|
|
442f270ee0 | ||
|
|
7ab74c6cc9 | ||
|
|
6d60baa2d6 | ||
|
|
6d3308621f | ||
|
|
fd49be1d9b | ||
|
|
c40a5648dd | ||
|
|
d9a8d2627a | ||
|
|
c7a88e2f12 | ||
|
|
9d2d170c2d | ||
|
|
df3aa22c59 | ||
|
|
a4aabfcdae | ||
|
|
ce99e70bf9 | ||
|
|
963b1aa6b1 | ||
|
|
008ac2876b | ||
|
|
2330b166f6 | ||
|
|
23c0e01565 | ||
|
|
13073bc98d | ||
|
|
8c319903dd | ||
|
|
2334cbd78a | ||
|
|
0cae954f80 | ||
|
|
c60446a015 | ||
|
|
d0c6a4ee6d | ||
|
|
f2d03a511e | ||
|
|
367233c318 | ||
|
|
9461c1692a | ||
|
|
3b32605b5e | ||
|
|
4d21f8d022 | ||
|
|
aac67570d4 | ||
|
|
5f2c465274 | ||
|
|
fdaa0bc876 | ||
|
|
a692d6be09 | ||
|
|
efbb9648c4 | ||
|
|
3d73153e59 | ||
|
|
8fa2256fb0 | ||
|
|
4fe974e7a8 | ||
|
|
21f76a8f27 | ||
|
|
aeb287fa1d | ||
|
|
1405e8821c | ||
|
|
37e31bac5b | ||
|
|
d31b696846 | ||
|
|
cc01c1f0db | ||
|
|
4a7076e01c | ||
|
|
d306bb25dc | ||
|
|
457c80fe76 | ||
|
|
bb972f8449 | ||
|
|
e6ef64968b | ||
|
|
6f3b87cfd1 | ||
|
|
f449feb3f8 | ||
|
|
b179c8e2b7 | ||
|
|
6aa0a4a47f | ||
|
|
766140f483 | ||
|
|
52aa8b868a | ||
|
|
8a3a4d6fae | ||
|
|
94f212a411 | ||
|
|
4e1dce70a3 | ||
|
|
bbf48a0dd0 | ||
|
|
a35e8f3315 | ||
|
|
205de7233e | ||
|
|
abb5dc5739 | ||
|
|
3a5a29efc0 | ||
|
|
9d249406e3 | ||
|
|
42d9e7a090 | ||
|
|
c202c0d705 | ||
|
|
8a1f9b7de6 | ||
|
|
18820c383d | ||
|
|
b38b879ee3 | ||
|
|
7fc7d626bc | ||
|
|
c8a0f1d0de | ||
|
|
c8aedc6f29 | ||
|
|
1e7ce8bb5c | ||
|
|
5386ca1592 | ||
|
|
08ed019426 | ||
|
|
55c6a5aa27 | ||
|
|
bd6bbf864a | ||
|
|
703335c2f1 | ||
|
|
c04fa496bf | ||
|
|
b9d19cfcb4 | ||
|
|
d8f093b226 | ||
|
|
63a2d83d26 | ||
|
|
7e42e98cb6 | ||
|
|
93deebe923 | ||
|
|
1eecf4b2c7 | ||
|
|
e7fc4ef1e7 | ||
|
|
3c54d4af15 | ||
|
|
ebfbf0e1f8 | ||
|
|
14aa4036e0 | ||
|
|
0c60d54c3f | ||
|
|
e510d279a2 | ||
|
|
be6f1f9c4a | ||
|
|
b1fb177e4b | ||
|
|
ec187fe109 | ||
|
|
9ec329b7ae | ||
|
|
d08bd4e866 | ||
|
|
941d5d7cd9 | ||
|
|
ef8d85773c | ||
|
|
e668d488b4 | ||
|
|
d4eb5facfd | ||
|
|
a1285b120b | ||
|
|
8650876e2b | ||
|
|
81ab12c89c | ||
|
|
4ddb8cec85 | ||
|
|
711c566498 | ||
|
|
cc5336900c | ||
|
|
291a8f5c1f | ||
|
|
8c0e98ed43 | ||
|
|
7a976c0239 | ||
|
|
fb557b9130 | ||
|
|
b56a930f60 | ||
|
|
5819ef346b | ||
|
|
b3dcc82c71 | ||
|
|
06e8308dc2 | ||
|
|
c8a9c9b84e | ||
|
|
e85b49c573 | ||
|
|
c7c6dc4e67 | ||
|
|
172d668416 | ||
|
|
b651dc845b | ||
|
|
c755f44153 | ||
|
|
ed28ce1874 | ||
|
|
194af0e985 | ||
|
|
ab3015df6b | ||
|
|
f36df159e0 | ||
|
|
61462cf57e | ||
|
|
427d186c86 | ||
|
|
84e9c47a67 | ||
|
|
18989d593a | ||
|
|
fc624359c5 | ||
|
|
1914573634 | ||
|
|
1fd36458a6 | ||
|
|
37ee0e568f | ||
|
|
3f8363a5b2 | ||
|
|
e6c0011789 | ||
|
|
eb37a495a2 | ||
|
|
54542f7f07 | ||
|
|
8e38910dd8 | ||
|
|
31b3f778fc | ||
|
|
ca3275757b | ||
|
|
501a314597 | ||
|
|
447c0bffdc | ||
|
|
46df59d77a | ||
|
|
8c85e240b7 | ||
|
|
2464d01891 | ||
|
|
66642a19c5 | ||
|
|
f7f4e92e0a | ||
|
|
2674bf22d8 | ||
|
|
351e0f3a0b | ||
|
|
ff7dc95e93 | ||
|
|
4e4d3418b3 | ||
|
|
3659b5b5c9 | ||
|
|
65e1b60fb7 | ||
|
|
e2427fe299 | ||
|
|
b08f882324 | ||
|
|
2a31ece0c6 | ||
|
|
cafa4211a6 | ||
|
|
82b50d3059 | ||
|
|
39cb582e07 | ||
|
|
fe6645a420 | ||
|
|
a49816f4eb | ||
|
|
7ac97f854c | ||
|
|
8f203852ca | ||
|
|
c342f7bce6 | ||
|
|
fe1c5df9d5 | ||
|
|
8aa7a55559 | ||
|
|
e9461586cb | ||
|
|
a91f2de26a | ||
|
|
5a4ae99283 | ||
|
|
437d030502 | ||
|
|
f3d45eff69 | ||
|
|
f22e39e22b | ||
|
|
7470a3b813 | ||
|
|
0b2e836e3d | ||
|
|
c3d57eef4f | ||
|
|
ca2571b438 | ||
|
|
6c926b8876 | ||
|
|
5517a913d4 | ||
|
|
ef7720ff06 | ||
|
|
daa13b4b30 | ||
|
|
9d4e237c09 | ||
|
|
883c169ef7 | ||
|
|
2b2b07f6b4 | ||
|
|
f338b68f36 | ||
|
|
c877b5fc70 | ||
|
|
6aeec81072 | ||
|
|
3f78c664eb | ||
|
|
3b7df1d5c2 | ||
|
|
b6fc063c75 | ||
|
|
7b56817ae6 | ||
|
|
75c8c3f50b | ||
|
|
be07ff2129 | ||
|
|
56846b258c | ||
|
|
f67310c8fa | ||
|
|
3dff3a1d4a | ||
|
|
142d30b1c6 | ||
|
|
c925e88475 | ||
|
|
56392e41d0 | ||
|
|
cd7b6450c6 | ||
|
|
de6a9f5811 | ||
|
|
d7295948fd | ||
|
|
f4c3e412a2 | ||
|
|
0d461e14d9 | ||
|
|
845c2571fe | ||
|
|
d5c02d1031 | ||
|
|
30e93a9372 | ||
|
|
e5cdcd190c | ||
|
|
271f1cd71b | ||
|
|
4abb790e12 | ||
|
|
89c9d4dfc4 | ||
|
|
5511c15921 | ||
|
|
e160f9a0f6 | ||
|
|
65ea341ed0 | ||
|
|
561827e896 | ||
|
|
1315aceb44 | ||
|
|
19afd89df5 | ||
|
|
cbcc893f64 | ||
|
|
a41bae3132 | ||
|
|
8ef8388c32 | ||
|
|
e2d4a0fde8 | ||
|
|
65b1d61295 | ||
|
|
1b38e73eb2 | ||
|
|
e2afee3275 | ||
|
|
7f2ecbd04f | ||
|
|
21dbaa1a03 | ||
|
|
09c1ea992c | ||
|
|
c8c327b6ab | ||
|
|
3bb801f579 | ||
|
|
ca49d8adb3 | ||
|
|
88b15797a0 | ||
|
|
28ebbd229c | ||
|
|
d7f6f46805 | ||
|
|
c41d6965ab | ||
|
|
602119fa41 | ||
|
|
4c2a9b47f5 | ||
|
|
5a26fefd6b | ||
|
|
85d26f7320 | ||
|
|
9487af1852 | ||
|
|
a5b09d7846 | ||
|
|
6ba5056c96 | ||
|
|
50b4d05ef5 | ||
|
|
13ebe6d0e1 | ||
|
|
95dedf0d80 | ||
|
|
89a9368166 | ||
|
|
c10e6159da | ||
|
|
c30693b8a8 | ||
|
|
7fc4f61182 | ||
|
|
b44ab88927 | ||
|
|
2ca81f965a | ||
|
|
9f4dc1e382 | ||
|
|
5ec9704e7f | ||
|
|
7ad0cfd5f6 | ||
|
|
ac8f679dfd | ||
|
|
a7ee2ef3a6 | ||
|
|
6e7edd9824 | ||
|
|
81b310086f | ||
|
|
cce57c7229 | ||
|
|
9cffa3dd67 | ||
|
|
7b3a59455d | ||
|
|
fefe5659d3 | ||
|
|
db72e22e61 | ||
|
|
a85ed709af | ||
|
|
e24d1a1261 | ||
|
|
d6f1bf18de | ||
|
|
97e5d923fa | ||
|
|
36762a6e46 | ||
|
|
40a9f9dd85 | ||
|
|
85a52523cf | ||
|
|
5ed7974099 | ||
|
|
70ca9ce2e0 | ||
|
|
af9f555e8f | ||
|
|
08b9e7b5b5 | ||
|
|
84f74c53b5 | ||
|
|
762bae907c | ||
|
|
2b738fa14b | ||
|
|
8aa745471b | ||
|
|
63950f572a | ||
|
|
81aab7e86f | ||
|
|
1fd5fd4832 | ||
|
|
ceaf478a84 | ||
|
|
61256f98ca | ||
|
|
818ed5d189 | ||
|
|
0ca00e5059 | ||
|
|
a2c743167d | ||
|
|
786641662c | ||
|
|
8380896deb | ||
|
|
1152689f34 | ||
|
|
d2afdc82f1 | ||
|
|
5bf90ae31d | ||
|
|
b533e3d3e1 | ||
|
|
4d9df309c8 | ||
|
|
65126365a6 | ||
|
|
0afe403057 | ||
|
|
d500353722 | ||
|
|
eea8b4dfbf | ||
|
|
20a9150ea3 | ||
|
|
c51e613568 | ||
|
|
69a887fb05 | ||
|
|
01c1d150c6 | ||
|
|
c51c09348e | ||
|
|
0a4df191a7 | ||
|
|
760995773e | ||
|
|
94ff8a9b04 | ||
|
|
10d5529f79 | ||
|
|
2b511b67c3 | ||
|
|
b595cdd31e | ||
|
|
e64870ca58 | ||
|
|
a40f8d5b3a | ||
|
|
61b8871ead | ||
|
|
4b5a3ed44d | ||
|
|
7d6b7b2691 | ||
|
|
3dba46b74f | ||
|
|
2767e31a28 | ||
|
|
40886bcf08 | ||
|
|
04dde74572 | ||
|
|
29f3ac065f | ||
|
|
d2b30b4f9c | ||
|
|
3a42663dea | ||
|
|
905d0ca409 | ||
|
|
7e2c78666e | ||
|
|
6a5f0225fe | ||
|
|
ddb01fca31 | ||
|
|
684a3cd49e | ||
|
|
ad5e42115b | ||
|
|
2d6b8d0c47 | ||
|
|
61471e5449 | ||
|
|
b6f7ab7a9c | ||
|
|
2d061be98e | ||
|
|
d6e97b8c76 | ||
|
|
9e44660746 | ||
|
|
03e6ca58ab | ||
|
|
e884cc1f75 | ||
|
|
94c63b0554 | ||
|
|
c7c8c40a70 | ||
|
|
91c726c706 | ||
|
|
c9805e7ac9 | ||
|
|
a4db0e40e3 | ||
|
|
305b55cb2a | ||
|
|
272ca1ac4f | ||
|
|
bbc6a1b38f | ||
|
|
525c235d3b | ||
|
|
0e93713464 | ||
|
|
8f60e103f9 | ||
|
|
9cc702241d | ||
|
|
0d61c44232 | ||
|
|
9a8faac316 | ||
|
|
05f710cb5c | ||
|
|
c6184769e7 | ||
|
|
515d1bd920 | ||
|
|
b19cb17bba | ||
|
|
c1e808bce6 | ||
|
|
d8b7292d4b | ||
|
|
edd5e2f5bc | ||
|
|
efc6cb73b2 | ||
|
|
ecd79dc34b | ||
|
|
cdfc8b825d | ||
|
|
301344c96d | ||
|
|
5279995c3b | ||
|
|
5176b06b59 | ||
|
|
ed61ac624d | ||
|
|
4da6e3ecee | ||
|
|
9e5561936a | ||
|
|
843cd0eff6 | ||
|
|
6b6ee934a1 | ||
|
|
aea57ffaf4 | ||
|
|
87b48661fa | ||
|
|
556fa44858 | ||
|
|
1c3e196508 | ||
|
|
9b6812ad0c | ||
|
|
b7944c7fa4 | ||
|
|
2fbedca746 | ||
|
|
340d04a48c | ||
|
|
460a383ffc | ||
|
|
52c4e3a256 | ||
|
|
4338f11eb1 | ||
|
|
42bab052e0 | ||
|
|
0cb377618e | ||
|
|
5e4d25b957 | ||
|
|
153d1853fa | ||
|
|
22a3448461 | ||
|
|
2cad869680 | ||
|
|
bc912a8ea4 | ||
|
|
db9176c284 | ||
|
|
06308210c0 | ||
|
|
63d9904370 | ||
|
|
caaeff5cb7 | ||
|
|
d8c93d3455 | ||
|
|
cb28e5fddc | ||
|
|
7d7ec1a00b | ||
|
|
a5bc8dfa3f | ||
|
|
d74f055180 | ||
|
|
73be6c35a6 | ||
|
|
24f74e1400 | ||
|
|
8900e069f3 | ||
|
|
1dfec119bb | ||
|
|
9e23d35f01 | ||
|
|
cd2b240308 | ||
|
|
749f366a4a | ||
|
|
420aaa92fa | ||
|
|
985698bbc3 | ||
|
|
f9c9139f20 | ||
|
|
f308e7541f | ||
|
|
cb7ccd7854 | ||
|
|
a4953028d0 | ||
|
|
3d6485588d | ||
|
|
51bb9fede7 | ||
|
|
269c429959 | ||
|
|
fcdc84a12a | ||
|
|
ecdd9734eb | ||
|
|
84fc2c65af | ||
|
|
c8849a17b6 | ||
|
|
d8b49218e9 | ||
|
|
e95023e8cc | ||
|
|
878710e2cf | ||
|
|
0677d0a810 | ||
|
|
9c98fea8f4 | ||
|
|
e958f33450 | ||
|
|
937080b011 | ||
|
|
aee5803dd2 | ||
|
|
f1f394b871 | ||
|
|
81a32b56f0 | ||
|
|
a6aae70a55 | ||
|
|
823eb23773 | ||
|
|
1ff51822df | ||
|
|
500147e130 | ||
|
|
d90de18d99 | ||
|
|
ba4f48662f | ||
|
|
d208437c05 | ||
|
|
01faa2e1d7 | ||
|
|
c630c387d6 | ||
|
|
a774718607 | ||
|
|
9430c70d0d | ||
|
|
f3e893fddb | ||
|
|
11e144ca64 | ||
|
|
fbceab707e | ||
|
|
5b2efc43b9 | ||
|
|
8d85d1aa2d | ||
|
|
b469fc7577 | ||
|
|
9db54831c8 | ||
|
|
9b88bde09a | ||
|
|
aad03a74c5 | ||
|
|
55eb6e2e5c | ||
|
|
ca07355873 | ||
|
|
11a59e26b2 | ||
|
|
ec6d9e3521 | ||
|
|
230accd31e | ||
|
|
a24a4a747e | ||
|
|
1e97b5c27a | ||
|
|
a314ea1aa3 | ||
|
|
a77128d5f7 | ||
|
|
1b2673367e | ||
|
|
ce10e91a60 | ||
|
|
5244b37d2c | ||
|
|
1239c6716b | ||
|
|
67f6258ab0 | ||
|
|
9f63172b43 | ||
|
|
bd8bfeb525 | ||
|
|
4918c4ef4b | ||
|
|
00d9ea9344 | ||
|
|
33537cde76 | ||
|
|
3d5db5c9ca | ||
|
|
fdf339514d | ||
|
|
937c4e485a | ||
|
|
837c060e1f | ||
|
|
00bacd7dde | ||
|
|
781031775e | ||
|
|
97aee3d375 | ||
|
|
34698751f2 | ||
|
|
3c31460f2f | ||
|
|
d5cb60b19c | ||
|
|
3a7cfe3208 | ||
|
|
f079cdad64 | ||
|
|
2822303138 | ||
|
|
e38de75520 | ||
|
|
2723604d3e | ||
|
|
82ee051c1a | ||
|
|
7bdf49b7e0 | ||
|
|
32521aba6b | ||
|
|
819c4cde1c | ||
|
|
776c486b1a | ||
|
|
bcd97120a4 | ||
|
|
312bfb8509 | ||
|
|
11c9a50931 | ||
|
|
94c0656bcd | ||
|
|
13313d0b25 | ||
|
|
3a20db1d76 | ||
|
|
00148b4cc8 | ||
|
|
a31546b1ff | ||
|
|
361b62b8e2 | ||
|
|
37327b77a7 | ||
|
|
7ef8a5bb11 | ||
|
|
11cfb8af32 | ||
|
|
7315f7d283 | ||
|
|
7d58eb718e | ||
|
|
651be76776 | ||
|
|
4a5c6f1d39 | ||
|
|
5745d71d6a | ||
|
|
db62b7421a | ||
|
|
4084c57789 | ||
|
|
f90bec985a | ||
|
|
90f911c529 | ||
|
|
6c88b106db | ||
|
|
cef69d1b97 | ||
|
|
f76a7fb331 | ||
|
|
3e7b8b0663 | ||
|
|
a6eb3ad037 | ||
|
|
9468749384 | ||
|
|
37417fa1bb | ||
|
|
217146351e | ||
|
|
818ec33cef | ||
|
|
cd1671830a | ||
|
|
a5fca87dd0 | ||
|
|
f06ce55626 | ||
|
|
853085e755 | ||
|
|
2b7accaf68 | ||
|
|
5533d93172 | ||
|
|
f0e8c865fe | ||
|
|
36400c0a83 | ||
|
|
c5383557b5 | ||
|
|
b645007884 | ||
|
|
63ac137206 | ||
|
|
808cbf8e0b | ||
|
|
8ed77ba0c7 | ||
|
|
66c74c51e4 | ||
|
|
7a272ef0ab | ||
|
|
60b817ec8e | ||
|
|
a41ecaf7cc | ||
|
|
d41afa0e53 | ||
|
|
a6284e05e5 | ||
|
|
e56f61441d | ||
|
|
7b4b7dffa2 | ||
|
|
77a214ef9c | ||
|
|
cf2723aafb | ||
|
|
499e99cfc5 | ||
|
|
a7b83e9fe3 | ||
|
|
964504b9c3 | ||
|
|
ec65e66c58 | ||
|
|
e694b080be | ||
|
|
70894b3938 | ||
|
|
fb7115fc13 | ||
|
|
a619fc4fef | ||
|
|
7c6c5fd06f | ||
|
|
2970568eab | ||
|
|
62cb3a610e | ||
|
|
f600c163ca | ||
|
|
77cb68e5ac | ||
|
|
c6314576aa | ||
|
|
515c183070 | ||
|
|
63b9c0e6b8 | ||
|
|
84893b1664 | ||
|
|
835668d96d | ||
|
|
2bce15dc6e | ||
|
|
8f1a212b52 | ||
|
|
5c08bde0fa | ||
|
|
98a84c031e | ||
|
|
ea1715384e | ||
|
|
d9a4ee4f65 | ||
|
|
62017c4661 | ||
|
|
702b98f510 | ||
|
|
69aafd7d6a | ||
|
|
c1559dd8c8 | ||
|
|
4df1895560 | ||
|
|
cac92da6e4 | ||
|
|
5d39d85215 | ||
|
|
99b4c43fd5 | ||
|
|
b2f59d6813 | ||
|
|
c7d79bb893 | ||
|
|
aa80c468c4 | ||
|
|
6008cba2db | ||
|
|
caf56671dc | ||
|
|
44eccf5ee4 | ||
|
|
8f96e4847c | ||
|
|
ae3e307f33 | ||
|
|
3fe0c758ed | ||
|
|
7240fb32d2 | ||
|
|
e23a3461ba | ||
|
|
727eb0cfd7 | ||
|
|
3796076360 | ||
|
|
ef9576f8c4 | ||
|
|
94fc4cb8a2 | ||
|
|
ccb248db91 | ||
|
|
e7de447725 | ||
|
|
7ff5429cb7 | ||
|
|
17c581b4aa | ||
|
|
41e5c2939f | ||
|
|
7e2ab51298 | ||
|
|
03f917fd9c | ||
|
|
d24e10a728 | ||
|
|
a17ac1c16e | ||
|
|
dd6b972be4 | ||
|
|
7d0c9ba0d9 | ||
|
|
6fa211634f | ||
|
|
1ca24c7f38 | ||
|
|
bcfbccae59 | ||
|
|
20b75ce6ed | ||
|
|
2ea15d7bf5 | ||
|
|
18e14c597f | ||
|
|
06d75999d7 | ||
|
|
7047a7cae6 | ||
|
|
20d2124867 | ||
|
|
3c7a85361e | ||
|
|
1ffbbdac99 | ||
|
|
eeccca8842 | ||
|
|
e2d2dbd2ba | ||
|
|
c61f0409fb | ||
|
|
806be39a6d | ||
|
|
6170b0d059 | ||
|
|
bca838495e | ||
|
|
e31a747250 | ||
|
|
4cf430e146 | ||
|
|
ef554cf6ec | ||
|
|
fcd91daee6 | ||
|
|
396c78b46a | ||
|
|
4677a3fd89 | ||
|
|
834ab5c6b9 | ||
|
|
1599e8f7ff | ||
|
|
7430704002 | ||
|
|
4d7b19c8cb | ||
|
|
40f535cf3c | ||
|
|
17425dcaf7 | ||
|
|
6b87fc64af | ||
|
|
35174b0348 | ||
|
|
fd53541719 | ||
|
|
7c68bff9f5 | ||
|
|
6c64991951 | ||
|
|
ca04ff0f37 | ||
|
|
7742575cab | ||
|
|
cdcdce702d | ||
|
|
c80e04fe8d | ||
|
|
c3b3ea107a | ||
|
|
1dc530c549 | ||
|
|
8b0b70e757 | ||
|
|
b508a629e8 | ||
|
|
abb0dadead | ||
|
|
e6fb18df56 | ||
|
|
43ba13f3bc | ||
|
|
ba705f5563 | ||
|
|
34e188ec1f | ||
|
|
b0d97dd170 | ||
|
|
7caeae61f5 | ||
|
|
416ace4c86 | ||
|
|
979041ee91 | ||
|
|
f0939b8af5 | ||
|
|
d7a7002bdd | ||
|
|
d9601de075 | ||
|
|
ef570558cf | ||
|
|
db3e81408f | ||
|
|
e8771cdea8 | ||
|
|
057eab2173 | ||
|
|
e2a7024eeb | ||
|
|
4650986dfa | ||
|
|
868b5e4617 | ||
|
|
f12860c7b1 | ||
|
|
8f751812a6 | ||
|
|
07a5092eb3 | ||
|
|
29c9c92ba6 | ||
|
|
edfa327158 | ||
|
|
869a6e66cc | ||
|
|
36abbfc048 | ||
|
|
cfc3e6d2f4 | ||
|
|
e38dbee6a6 | ||
|
|
68a7c857c0 | ||
|
|
80eef2ab8c | ||
|
|
1d652aa746 | ||
|
|
b07c43aa36 | ||
|
|
3880c8dc2c | ||
|
|
c0ab2ac297 | ||
|
|
de684dcb63 | ||
|
|
29ef1db86b | ||
|
|
5dfd8a61be | ||
|
|
358e2b3ccf | ||
|
|
4203065a06 | ||
|
|
bc4e0190a0 | ||
|
|
dd7004cbc9 | ||
|
|
bdc5c8f620 | ||
|
|
02d36e22ee | ||
|
|
331e8c4aa6 | ||
|
|
d622277c11 | ||
|
|
8f781ea4ab | ||
|
|
ebc1e5bf12 | ||
|
|
ce9a61622e | ||
|
|
e4891e699f | ||
|
|
d8765578c8 | ||
|
|
3a034ecec8 | ||
|
|
a3dea45089 | ||
|
|
de99c8a5e4 | ||
|
|
d3b8dbeea0 | ||
|
|
cff2f64155 | ||
|
|
7b8de35405 | ||
|
|
02ae0df2cc | ||
|
|
b386cea69d | ||
|
|
758ffb75a9 | ||
|
|
78fbc7f392 | ||
|
|
9c58472576 | ||
|
|
f8c4afc228 | ||
|
|
b169d65619 | ||
|
|
9bf0d4f804 | ||
|
|
4443f57f8a | ||
|
|
ea5d8590d5 | ||
|
|
5d5feb4c71 | ||
|
|
feb5351ec3 | ||
|
|
7630c25ef3 | ||
|
|
24238094e5 | ||
|
|
7cc9a03db8 | ||
|
|
2b2e8508d9 | ||
|
|
a70716f225 | ||
|
|
d9fcc46994 | ||
|
|
2d8acec6f0 | ||
|
|
cd06d8c63a | ||
|
|
a06ca55107 | ||
|
|
9686a9ba77 | ||
|
|
f7f4043ccd | ||
|
|
b7b55173a6 | ||
|
|
954253c7e2 | ||
|
|
cbe4d2cd7f | ||
|
|
40101129b5 | ||
|
|
4bb32c6d09 | ||
|
|
6e09ceeda6 | ||
|
|
d6a6a53623 | ||
|
|
4a97052708 | ||
|
|
3a4902ad4a | ||
|
|
77d14bc218 | ||
|
|
1d2a39a855 | ||
|
|
98b53b6b3d | ||
|
|
0148d8beaf | ||
|
|
5bfd84d3be | ||
|
|
351eb95feb | ||
|
|
56788f0933 | ||
|
|
017a376616 | ||
|
|
c5888cec66 | ||
|
|
3d5ad29eac | ||
|
|
c608636b7a | ||
|
|
1a97107b2d | ||
|
|
5ca3fbeaea | ||
|
|
44896db668 | ||
|
|
12efb87a23 | ||
|
|
9181be86ba | ||
|
|
053b01e036 | ||
|
|
86041d0968 | ||
|
|
bd87f63e91 | ||
|
|
b79b49e8f3 | ||
|
|
a0dde39d97 | ||
|
|
2e03868021 | ||
|
|
29384c2ba3 | ||
|
|
320743ab8d | ||
|
|
399e171083 | ||
|
|
184164b677 | ||
|
|
a8bd196234 | ||
|
|
239d425940 | ||
|
|
baa3c1461c | ||
|
|
fa8e398e90 | ||
|
|
6d9675a299 | ||
|
|
91e8ce62d4 | ||
|
|
06e641015f | ||
|
|
1c83059482 | ||
|
|
90b24d824a | ||
|
|
62457d0e48 | ||
|
|
90c96f7479 | ||
|
|
f87adebe41 | ||
|
|
8f24cc8d13 | ||
|
|
992802d196 | ||
|
|
8546d6730c | ||
|
|
0092289105 | ||
|
|
7c3923ad00 | ||
|
|
ef82039401 | ||
|
|
b01b9758e0 | ||
|
|
88b00f689b | ||
|
|
0a340d5d57 | ||
|
|
50545a83b8 | ||
|
|
4a57ff40d8 | ||
|
|
0238455a5a | ||
|
|
a53e963001 | ||
|
|
984608e23f | ||
|
|
f680c83d2d | ||
|
|
a79e51c76f | ||
|
|
2dfb349609 | ||
|
|
766f21b525 | ||
|
|
733dfa1467 | ||
|
|
63aa840b55 | ||
|
|
8b2d544576 | ||
|
|
d6046d2422 | ||
|
|
409939360f | ||
|
|
1d21f39fbc | ||
|
|
a477140a4b | ||
|
|
1bbf2d8ce6 | ||
|
|
40a65eec51 | ||
|
|
8431ebf2e8 | ||
|
|
bdcc0c5373 | ||
|
|
9cbf331533 | ||
|
|
77640714cc | ||
|
|
9457d95c3f | ||
|
|
c2ff949f2d | ||
|
|
ba8685a122 | ||
|
|
55464ed0dd | ||
|
|
fdf3691c87 | ||
|
|
aa6699cf3e | ||
|
|
b79b48baac | ||
|
|
5d22dbd99e | ||
|
|
4686bb5584 | ||
|
|
1f62b8f0b6 | ||
|
|
5759ed3728 | ||
|
|
827fbfb78f | ||
|
|
dc363de610 | ||
|
|
b9d6a235e3 | ||
|
|
ebc57fe494 | ||
|
|
e224ec4ae0 | ||
|
|
a5da347177 | ||
|
|
a257b15f86 | ||
|
|
a70cc53d82 | ||
|
|
1df2de9202 | ||
|
|
9e394ea349 | ||
|
|
b55685d610 | ||
|
|
2156aac046 | ||
|
|
6914465e3d | ||
|
|
f3847ec6f3 | ||
|
|
e1fe8d1d89 | ||
|
|
675c937a4a | ||
|
|
c8f53bdf8e | ||
|
|
3541d5adde | ||
|
|
b52da7c9fc | ||
|
|
de57daa3cd | ||
|
|
e70e011a9c | ||
|
|
99febb99f1 | ||
|
|
874d79be36 | ||
|
|
b33663c9f8 | ||
|
|
7e69fa39eb | ||
|
|
de06490539 | ||
|
|
40a30c24a0 | ||
|
|
de04c12d3c | ||
|
|
38fb53b058 | ||
|
|
ed617c5943 | ||
|
|
986337da0c | ||
|
|
8dd7621f29 | ||
|
|
88d862303d | ||
|
|
cc274ffebe | ||
|
|
28a108f79b | ||
|
|
b9f75bf7d2 | ||
|
|
39994d5797 | ||
|
|
8e28be6558 | ||
|
|
8a65bef004 | ||
|
|
b94dc5044b | ||
|
|
b853c00dd4 | ||
|
|
7a0bc81f48 | ||
|
|
10bc326490 | ||
|
|
1920f8158e | ||
|
|
0ed2ba0183 | ||
|
|
95adc0aec1 | ||
|
|
ebee80d10e | ||
|
|
63836185d9 | ||
|
|
d0195e0509 | ||
|
|
5d9bcd9918 | ||
|
|
db04c26d24 | ||
|
|
56b399655e | ||
|
|
24e15c0568 | ||
|
|
f0c516e82d | ||
|
|
f38203ef62 | ||
|
|
a77c026803 | ||
|
|
5b6306671c | ||
|
|
25610222bc | ||
|
|
c17f941fb9 | ||
|
|
ae6ab1d203 | ||
|
|
92accf99b4 | ||
|
|
b02702fe80 | ||
|
|
5c549ec6e5 | ||
|
|
af459a5a28 | ||
|
|
07770601f6 | ||
|
|
cc96b86b3a | ||
|
|
1547f4d8b2 | ||
|
|
75054fcc70 | ||
|
|
390b3b173b | ||
|
|
78daa65d28 | ||
|
|
3bbdd08d24 | ||
|
|
cec1f12918 | ||
|
|
d923ae2107 | ||
|
|
85931155e6 | ||
|
|
4fd87aca09 | ||
|
|
600e0ec7e3 | ||
|
|
51fbff1a4a | ||
|
|
03b1389ee5 | ||
|
|
8f014e9d82 | ||
|
|
cecc6f7561 | ||
|
|
62ba81c6a6 | ||
|
|
c5e3422fcd | ||
|
|
bd5a46b4ab | ||
|
|
3a972bbbab | ||
|
|
7768ea28bd | ||
|
|
75add44e86 | ||
|
|
7d94365cbf | ||
|
|
2d830fb8e7 | ||
|
|
633bf36fe7 | ||
|
|
c0a5e23d95 | ||
|
|
d3798344dd | ||
|
|
ed37460402 | ||
|
|
9b6ba65cdb | ||
|
|
42a9631926 | ||
|
|
676a8a6421 | ||
|
|
cdbf022ce0 | ||
|
|
db79e1271e | ||
|
|
d2b3efacf9 | ||
|
|
a2ab94f971 | ||
|
|
a0d92d764b | ||
|
|
649b78e3f2 | ||
|
|
e7df1c3e56 | ||
|
|
53833ae0c3 | ||
|
|
66b914774a | ||
|
|
fc89feec4e | ||
|
|
d311dbd9d5 | ||
|
|
f97aa67100 | ||
|
|
9a8add780c | ||
|
|
3b48f1d042 | ||
|
|
332b54e7a5 | ||
|
|
007b2f0c88 | ||
|
|
3f083862e7 | ||
|
|
39619d5277 | ||
|
|
d4fe01f9b9 | ||
|
|
6db61b4357 | ||
|
|
f245cbf7f2 | ||
|
|
6f2b04669f | ||
|
|
9a46081d0b | ||
|
|
3c7e507ca1 | ||
|
|
7117725e69 | ||
|
|
ba428c6cfe | ||
|
|
d76c924ad1 | ||
|
|
cad7debc5b | ||
|
|
40725aa2a2 | ||
|
|
6034891fed | ||
|
|
9dd9862d33 | ||
|
|
48c72e319b | ||
|
|
4b6208fd9c | ||
|
|
168904a159 | ||
|
|
28f1498ec3 | ||
|
|
d3028e10d3 | ||
|
|
5eb0b77a8a | ||
|
|
4aace5b95a | ||
|
|
044dbd4a65 | ||
|
|
5dbae7c9d7 | ||
|
|
ec44cb2761 | ||
|
|
b06cf55c0b | ||
|
|
b601f6a138 | ||
|
|
ddebc63488 | ||
|
|
35440822be | ||
|
|
f4c6bcfb8e | ||
|
|
6365c5c9ef | ||
|
|
dd0334d30d | ||
|
|
c462a44973 | ||
|
|
6f88f5db83 | ||
|
|
93617f62a2 | ||
|
|
61d5f39408 | ||
|
|
c1fddaa7dd | ||
|
|
188aa14d82 | ||
|
|
5c25dd5b6d | ||
|
|
7c579cf7b7 | ||
|
|
c755c823fa | ||
|
|
116588c237 | ||
|
|
f02c1e4dc7 | ||
|
|
c4e8cc1641 | ||
|
|
93e68ad147 | ||
|
|
7ba88a83f0 | ||
|
|
c9293327ce | ||
|
|
fa1f35a89e | ||
|
|
845ce7a711 | ||
|
|
2b40007563 | ||
|
|
217034c4a7 | ||
|
|
0b9d4f17ab | ||
|
|
7fb0ec12dd | ||
|
|
3581158a7b | ||
|
|
facfa73214 | ||
|
|
0ef4a86d42 | ||
|
|
d4ec4795c3 | ||
|
|
b13d0aa283 | ||
|
|
a6965342e7 | ||
|
|
752dfa5b7f | ||
|
|
87aa283f22 | ||
|
|
6598ae080f | ||
|
|
7c5e8a66e4 | ||
|
|
c9577bcdc5 | ||
|
|
8254c2e83c | ||
|
|
20a9ac841d | ||
|
|
ae86b75d89 | ||
|
|
93a0afe612 | ||
|
|
439027220b | ||
|
|
4a07272d7a | ||
|
|
81432b54a3 | ||
|
|
b84a6e0c02 | ||
|
|
37dc5a00e8 | ||
|
|
e6edf85fbe | ||
|
|
cb533a26f2 | ||
|
|
a7278f76a8 | ||
|
|
80bd32382f | ||
|
|
db21ced104 | ||
|
|
717c6555cb | ||
|
|
a412e4af5c | ||
|
|
3350bf1ac6 | ||
|
|
4aa3353a1d | ||
|
|
ff48a58537 | ||
|
|
08fa511d17 | ||
|
|
c295115ffc | ||
|
|
5fb14610ec | ||
|
|
e87c2350b7 | ||
|
|
44e691e840 | ||
|
|
b5a7234cf3 | ||
|
|
d12509957f | ||
|
|
f01e7b7e20 | ||
|
|
6aa156d956 | ||
|
|
ef5ea93de1 | ||
|
|
b4913f51f2 | ||
|
|
dc3e960e79 | ||
|
|
0fe79b5288 | ||
|
|
1f76bd1942 | ||
|
|
3545f80920 | ||
|
|
0b2d1564ef | ||
|
|
fdacf824b3 | ||
|
|
5c01a44644 | ||
|
|
4eb49d872b | ||
|
|
34e5f29419 | ||
|
|
f4910f0a8e | ||
|
|
c8c14611dc | ||
|
|
491201991e | ||
|
|
401f3574fd | ||
|
|
173a86172c | ||
|
|
9ecbff024a | ||
|
|
1b5be34be4 | ||
|
|
ceb3a997b6 | ||
|
|
b1ead7fec8 | ||
|
|
d534dbb006 | ||
|
|
e56377117b | ||
|
|
63483dc6c3 | ||
|
|
66ceafd010 | ||
|
|
dd793650c3 | ||
|
|
afd829307d | ||
|
|
09abdc0f12 | ||
|
|
ed4d17f578 | ||
|
|
aeeeb5a37b | ||
|
|
dcb2e51587 | ||
|
|
cbc2eaf908 | ||
|
|
8808031e7c | ||
|
|
23ac7213d3 | ||
|
|
add7b44d0b | ||
|
|
1e4b7599a7 | ||
|
|
54443b038a | ||
|
|
c3f03e3f95 | ||
|
|
18135624f6 | ||
|
|
11238d6b71 | ||
|
|
848f94b1e0 | ||
|
|
d47cfe9504 | ||
|
|
70dccff293 | ||
|
|
e40873710b | ||
|
|
b140ef3b7a | ||
|
|
3b7b74aa67 | ||
|
|
de8e5b2d69 | ||
|
|
afea33b0e3 | ||
|
|
b44fbc1e4f | ||
|
|
c4dee3dd8d | ||
|
|
091e024032 | ||
|
|
0e030f7f48 | ||
|
|
3341c9e3bf | ||
|
|
91ddc00f7e | ||
|
|
3049ba0b24 | ||
|
|
55a161fafe | ||
|
|
349af24c81 | ||
|
|
788f1c4b3e | ||
|
|
889af461c6 | ||
|
|
df86e59089 | ||
|
|
c6bf69cce4 | ||
|
|
e492012004 | ||
|
|
94c46f9881 | ||
|
|
1eaa9d32ea | ||
|
|
0e2e8d2e2a | ||
|
|
cfb39c6364 | ||
|
|
173499f496 | ||
|
|
1081049074 | ||
|
|
961dc85514 | ||
|
|
6434acd492 | ||
|
|
ccb27c89d8 | ||
|
|
8053256203 | ||
|
|
4abd7301fd | ||
|
|
d6fe5ab417 | ||
|
|
a739fbdf1d | ||
|
|
c90a1ab6dc | ||
|
|
05ef68e079 | ||
|
|
dee4a7f3c7 | ||
|
|
75753df0d8 | ||
|
|
30c5d78647 | ||
|
|
6bb4db3842 | ||
|
|
cc0907fcd7 | ||
|
|
20b018bcc7 | ||
|
|
aafe2fa8d0 | ||
|
|
ee7bd73b3f | ||
|
|
b67f3bd629 | ||
|
|
38b81e79f8 | ||
|
|
b73c549131 | ||
|
|
d21d9f0141 | ||
|
|
7bb85032a1 | ||
|
|
d90446ad28 | ||
|
|
8b5e2f5528 | ||
|
|
1bcc3ab7f1 | ||
|
|
3359c3cd45 | ||
|
|
af812f3c90 | ||
|
|
1e6201093b | ||
|
|
959ea69427 | ||
|
|
cea744a914 | ||
|
|
e8baf48764 | ||
|
|
41242a2ae1 | ||
|
|
f1dee488a7 | ||
|
|
3b4ff1818e | ||
|
|
497145b1b5 | ||
|
|
10eb41d319 | ||
|
|
4daf2e4a3d | ||
|
|
f3266a5111 | ||
|
|
27cac4e8b8 | ||
|
|
60b9a5b9da | ||
|
|
eaaa62a7f3 | ||
|
|
6ce732ec3d | ||
|
|
fb0cc61e09 | ||
|
|
be29b5daf8 | ||
|
|
f010adabd0 | ||
|
|
c93b263b1f | ||
|
|
15f34d6b54 | ||
|
|
d0eeb55999 | ||
|
|
08c0d39b23 | ||
|
|
d0ecde3277 | ||
|
|
45ec57afd7 | ||
|
|
b0cd053083 | ||
|
|
698a11be58 | ||
|
|
efb08fb1e1 | ||
|
|
f89bc8422e | ||
|
|
4bf4889a08 | ||
|
|
01ab8ba38e | ||
|
|
ae6d15e812 | ||
|
|
1abfbe1d34 | ||
|
|
d3095297c2 | ||
|
|
79d40d5644 | ||
|
|
008e305a84 | ||
|
|
0379611edd | ||
|
|
96d883c1c7 | ||
|
|
be0f262e37 | ||
|
|
1676adf071 | ||
|
|
a5d5630067 | ||
|
|
275956caba | ||
|
|
bf8ed87fc9 | ||
|
|
fb3afac097 | ||
|
|
eda8b037a9 | ||
|
|
8ef14f7a54 | ||
|
|
9974e35656 | ||
|
|
15bc5431b6 | ||
|
|
f767531d89 | ||
|
|
7285ada9dd | ||
|
|
b9b9773df9 | ||
|
|
c29a83b259 | ||
|
|
fa45e66da6 | ||
|
|
7cbcdddac9 | ||
|
|
a2f17900da | ||
|
|
fb7e97b8ad | ||
|
|
0c92a8a8e9 | ||
|
|
dcc59380e5 | ||
|
|
f9bf25f96d | ||
|
|
cbcbea8b08 | ||
|
|
62eb4f20da | ||
|
|
43d5311e5e | ||
|
|
a6f08a09d5 | ||
|
|
d93f5d7785 | ||
|
|
c7170e6dc2 | ||
|
|
bcf3ca7339 | ||
|
|
0388f5787a | ||
|
|
6514df9d96 | ||
|
|
8f5b9869dc | ||
|
|
580c5fe23f | ||
|
|
b0af5b26ba | ||
|
|
9e898932f6 | ||
|
|
1f873b93f6 | ||
|
|
f414707f11 | ||
|
|
505825056c | ||
|
|
38f7716738 | ||
|
|
a69d08b554 | ||
|
|
3ccdb64833 | ||
|
|
78d8bff599 | ||
|
|
a756fed70b | ||
|
|
3e2a1e3548 | ||
|
|
96b2f2b3a4 | ||
|
|
d81d7d4f68 | ||
|
|
20244c4fb5 | ||
|
|
b50d31ffe2 | ||
|
|
d709a44960 | ||
|
|
4e4d07ced6 | ||
|
|
d775bc9d7e | ||
|
|
85528761eb | ||
|
|
ad3eac9ddb | ||
|
|
613f9fccd2 | ||
|
|
3d1741c904 | ||
|
|
26be14ba67 | ||
|
|
daa0755920 | ||
|
|
305d60e09b | ||
|
|
d0029efd02 | ||
|
|
fb4d42bf5b | ||
|
|
20eec53b14 | ||
|
|
8343db44db | ||
|
|
649652e373 | ||
|
|
e37ed7c32d | ||
|
|
f9a525068b | ||
|
|
aa11e6d62e | ||
|
|
6802d152da | ||
|
|
3b40f393d8 | ||
|
|
020443ae8a | ||
|
|
1d0baccffc | ||
|
|
5426f0f329 | ||
|
|
790249dd1a | ||
|
|
446a201d25 | ||
|
|
b6538d5e18 | ||
|
|
edd6043059 | ||
|
|
fe4ffeb7f1 | ||
|
|
27b3875bfb | ||
|
|
e2dbe8a0a2 | ||
|
|
29fc7910b7 | ||
|
|
22e2fdc707 | ||
|
|
584786eb9f | ||
|
|
d803d9eaf9 | ||
|
|
bad6575d83 | ||
|
|
fbcb7ae836 | ||
|
|
2c1a1b10c8 | ||
|
|
155fb16a8a | ||
|
|
b1ab2ce96a | ||
|
|
f299ba6218 | ||
|
|
d167ad1923 | ||
|
|
93626e8154 | ||
|
|
d5040c091a | ||
|
|
868daef0f0 | ||
|
|
dc8e85e7f2 | ||
|
|
22d32d7ca3 | ||
|
|
2d500f8074 | ||
|
|
452cdc17c6 | ||
|
|
bcbfee0321 | ||
|
|
dab2e7ede3 | ||
|
|
d91acb8352 | ||
|
|
373dd8058e | ||
|
|
de6310e52a | ||
|
|
8c297a4a4c | ||
|
|
4eb5c817bc | ||
|
|
07e4b26b9e | ||
|
|
b63aa62985 | ||
|
|
ca701c0580 | ||
|
|
e37043a6a8 | ||
|
|
7c26975d14 | ||
|
|
47f8a43637 | ||
|
|
1238c0cefe | ||
|
|
4c35fda045 | ||
|
|
780124c2f5 | ||
|
|
38e0af41ce | ||
|
|
601e99eec0 | ||
|
|
745a2adee7 | ||
|
|
9e83234df1 | ||
|
|
e45eeadf7d | ||
|
|
9a778cea6b | ||
|
|
20823bfc87 | ||
|
|
be3d703692 | ||
|
|
e2df5739f0 | ||
|
|
7bb11d6436 | ||
|
|
80b84212cc | ||
|
|
4a1bee769b | ||
|
|
de99a7aeaf | ||
|
|
a0a02701b0 | ||
|
|
1314ae1555 | ||
|
|
67cf0e745c | ||
|
|
538a2acbf5 | ||
|
|
8d0e453666 | ||
|
|
ace04f0b30 | ||
|
|
f8e25d6c4a | ||
|
|
b2bc43da4f | ||
|
|
cb12e540d2 | ||
|
|
39955af2fa | ||
|
|
86e1f0615d | ||
|
|
dc81ab6dee | ||
|
|
f8cf6a65ae | ||
|
|
ba909c696d | ||
|
|
df0515cebf | ||
|
|
46c0e14d67 | ||
|
|
97d7733464 | ||
|
|
afda84ef09 | ||
|
|
61d6e74102 | ||
|
|
8d74258ce2 | ||
|
|
5dfba0b834 | ||
|
|
056370ec08 | ||
|
|
4e2c254558 | ||
|
|
38c2bdb447 | ||
|
|
0cee4717e2 | ||
|
|
221b04c466 | ||
|
|
237e9b7191 | ||
|
|
9457e44a88 | ||
|
|
80a9d40a44 | ||
|
|
0715325a63 | ||
|
|
0a026fef0f | ||
|
|
5fbf650d2d | ||
|
|
dabdde0c3f | ||
|
|
b6ca92a7ef | ||
|
|
62f7339170 | ||
|
|
eaec682ea7 | ||
|
|
12110a4442 | ||
|
|
df597f53b2 | ||
|
|
d7d40254d4 | ||
|
|
e7c4a2cce6 | ||
|
|
0eb1c0cea6 | ||
|
|
07d35a8513 | ||
|
|
16c887814e | ||
|
|
22a50b72fd | ||
|
|
a79e1b6ca1 | ||
|
|
995296ef53 | ||
|
|
f4d5996a88 | ||
|
|
ab732b5435 | ||
|
|
241ff5cb6e | ||
|
|
ec2169e079 | ||
|
|
c75662e720 | ||
|
|
d567fd4842 | ||
|
|
0776dfc80e | ||
|
|
79a662fb93 | ||
|
|
8b009b7ee9 | ||
|
|
c4face30cc | ||
|
|
d4dbb5cb51 | ||
|
|
1e27187652 | ||
|
|
3ff278291f | ||
|
|
4e8bf216df | ||
|
|
e7b9100f1c | ||
|
|
08aa9790f3 | ||
|
|
5f13fd2dca | ||
|
|
f4c6f42c38 | ||
|
|
6a10d08189 | ||
|
|
f646360af6 | ||
|
|
95f265ebbf | ||
|
|
39d0142993 | ||
|
|
da16172244 | ||
|
|
71aded0fae | ||
|
|
e173b3ea41 | ||
|
|
6c4f9466b9 | ||
|
|
664196c5ef | ||
|
|
c8d5044e7a | ||
|
|
d8c31fe560 | ||
|
|
516db855f5 | ||
|
|
9cdcf08ab1 | ||
|
|
326fa73b22 | ||
|
|
79cacefd07 | ||
|
|
07e28bfee6 | ||
|
|
980b017fbe | ||
|
|
4567fd1eb0 | ||
|
|
8c150c23f3 | ||
|
|
b4fd570269 | ||
|
|
681a845ef3 | ||
|
|
6e051d73c1 | ||
|
|
e381e1a313 | ||
|
|
2d03ff63cf | ||
|
|
309de631ed | ||
|
|
ad240cf52f | ||
|
|
99e3a47dde | ||
|
|
3fa810b7b8 | ||
|
|
bad7316b80 | ||
|
|
4757c36233 | ||
|
|
9ca6180207 | ||
|
|
30179ad977 | ||
|
|
b799609749 | ||
|
|
efb6994ae7 | ||
|
|
cd129fb055 | ||
|
|
880a977dd6 | ||
|
|
6eceffb403 | ||
|
|
795e33881c | ||
|
|
d310c3857f | ||
|
|
837e275bfd | ||
|
|
7be6031e19 | ||
|
|
8c53908cc4 | ||
|
|
589b54984a | ||
|
|
3f30ed5251 | ||
|
|
3f9181905a | ||
|
|
29f3a81666 | ||
|
|
5efc43260e | ||
|
|
e01794a07f | ||
|
|
5fde095a6f | ||
|
|
3237af2d85 | ||
|
|
953b666ebd | ||
|
|
417bb4bf37 | ||
|
|
a55213d88a | ||
|
|
ec84d190f4 | ||
|
|
1b0bad72de | ||
|
|
931055708d | ||
|
|
15fd570b49 | ||
|
|
ff9c6bac0a | ||
|
|
713111254b | ||
|
|
5b1462a3e8 | ||
|
|
2bf18d8bda | ||
|
|
7f2e643e62 | ||
|
|
ef172592b8 | ||
|
|
5e51a438a7 | ||
|
|
7f768059e6 | ||
|
|
ea70175a17 | ||
|
|
74a736691a | ||
|
|
86ff44adfc | ||
|
|
58b763e935 | ||
|
|
5c90cc59aa | ||
|
|
710ab44073 | ||
|
|
b28c5e6807 | ||
|
|
e5ead9ed44 | ||
|
|
d99897cf9d | ||
|
|
701a7cae02 | ||
|
|
068b6a5470 | ||
|
|
45d597ac49 | ||
|
|
a518d3f33f | ||
|
|
2f05228d91 | ||
|
|
335ae0105f | ||
|
|
62ce7a0e37 | ||
|
|
afa0fb8da1 | ||
|
|
763d835f4e | ||
|
|
0289872dcd | ||
|
|
2810141bd6 | ||
|
|
93ea22c69d | ||
|
|
daf76a311c | ||
|
|
b94271a725 | ||
|
|
1456aeedf2 | ||
|
|
4c6589a57e | ||
|
|
5b9a61b7db | ||
|
|
96e71695c5 | ||
|
|
2e7dd1bde3 | ||
|
|
2de543f5f9 | ||
|
|
a6ee20fca4 | ||
|
|
2d2f159e04 | ||
|
|
5568e0c2ad | ||
|
|
cb2cc0cb9e | ||
|
|
5e573ca980 | ||
|
|
dcb4a315a6 | ||
|
|
4bd36fc29e | ||
|
|
1a7971ec82 | ||
|
|
c1eda034b3 | ||
|
|
2294d722c7 | ||
|
|
7d053be6d1 | ||
|
|
7a508661eb | ||
|
|
c976242ce5 | ||
|
|
2b77c372a3 | ||
|
|
b61cc67997 | ||
|
|
de8db1a86d | ||
|
|
abfdf0e1c2 | ||
|
|
1d662e354b | ||
|
|
663e9a9b5e | ||
|
|
8535409962 | ||
|
|
cd5623b348 | ||
|
|
673e051bd5 | ||
|
|
66c949057e | ||
|
|
aed09f0c64 | ||
|
|
c05f306b0d | ||
|
|
739fb99ced | ||
|
|
7fc82ccead | ||
|
|
8ae947f59c | ||
|
|
d34b493b7d | ||
|
|
4df6e0ee7d | ||
|
|
aac4ef05e4 | ||
|
|
ea2f53e166 | ||
|
|
f144ec67ab | ||
|
|
7e42dcf0b5 | ||
|
|
87c4dc313a | ||
|
|
0d29339898 | ||
|
|
6d83f18490 | ||
|
|
0ba125c2d7 | ||
|
|
6abd120a5c | ||
|
|
5cf7e89ce6 | ||
|
|
353786cb61 | ||
|
|
586beea21e | ||
|
|
b80454a1f4 | ||
|
|
19f80cf506 | ||
|
|
d01100bb15 | ||
|
|
e0414e4eb9 | ||
|
|
1eb10e3c22 | ||
|
|
4772fbcd4a | ||
|
|
18b61e35be | ||
|
|
bb7faf0fb3 | ||
|
|
1603742adc | ||
|
|
8a830e40bb | ||
|
|
d8adcf5a84 | ||
|
|
1d9a404f77 | ||
|
|
26dcaf6078 | ||
|
|
a91e4014bf | ||
|
|
06af327e5e | ||
|
|
35e3b889c3 | ||
|
|
5ef6ba0258 | ||
|
|
12754ff135 | ||
|
|
d09a1e254f | ||
|
|
b89ee67daf | ||
|
|
7bd256c311 | ||
|
|
4add7cd0b3 | ||
|
|
5ac20cc4cf | ||
|
|
9d7b0487d5 | ||
|
|
59aa84f6c8 | ||
|
|
765b03c868 | ||
|
|
41ce3db8f9 | ||
|
|
00e3ef757c | ||
|
|
84dc0b2959 | ||
|
|
2e48099070 | ||
|
|
77779bbcd9 | ||
|
|
e08bc01c33 | ||
|
|
bf24ee369f | ||
|
|
876f12db89 | ||
|
|
8b84459e13 | ||
|
|
dccfcc9663 | ||
|
|
203e1cc9b9 | ||
|
|
b612f0cdec | ||
|
|
961301fbec | ||
|
|
2a38d99cf1 | ||
|
|
7903328c2d | ||
|
|
56d2b4a80c | ||
|
|
2c6ecaab5b | ||
|
|
45d289a65e | ||
|
|
318c8c68b0 | ||
|
|
fbd47a7f3b | ||
|
|
07533f5658 | ||
|
|
66b7e3e1f5 | ||
|
|
4fee4d1903 | ||
|
|
90d70beea2 | ||
|
|
a7297d2685 | ||
|
|
86ae704e86 | ||
|
|
2d1e993fe1 | ||
|
|
04b550e435 | ||
|
|
c492ea77f1 | ||
|
|
61d9112ba7 | ||
|
|
d7fe36de71 | ||
|
|
db0bd3fa2d | ||
|
|
551619e772 | ||
|
|
29bae230a4 | ||
|
|
83be49156f | ||
|
|
561ae102fb | ||
|
|
a05e69b855 | ||
|
|
8eb772d80b | ||
|
|
1590693547 | ||
|
|
66f93ee541 | ||
|
|
8893df118e | ||
|
|
2c77cb5ca5 | ||
|
|
8a101f9e9a | ||
|
|
ce98d0184d | ||
|
|
402dea3c8b | ||
|
|
223cf4b2b2 | ||
|
|
8fb7e79bb3 | ||
|
|
5a2d386976 | ||
|
|
96622533e0 | ||
|
|
8814ce05a9 | ||
|
|
c15148fc07 | ||
|
|
3404ebbbb8 | ||
|
|
51494cabc8 | ||
|
|
1eb326683e | ||
|
|
98bcfbef7e | ||
|
|
9416980096 | ||
|
|
b34505c086 | ||
|
|
a65edf52ca | ||
|
|
d1513f2575 | ||
|
|
12d20c35be | ||
|
|
9f822c0991 | ||
|
|
96c338859b | ||
|
|
a2464dce73 | ||
|
|
53476b723d | ||
|
|
ca92a0af5c | ||
|
|
6e6cd90f6d | ||
|
|
adc84e1f93 | ||
|
|
20687d915a | ||
|
|
12a34f0b09 | ||
|
|
e5e49e4347 | ||
|
|
9f61256e5e | ||
|
|
ac6e370a78 | ||
|
|
a9c2c2178a | ||
|
|
c67419bb55 | ||
|
|
631c270fc7 | ||
|
|
3c82dfc0a5 | ||
|
|
063574023b | ||
|
|
5f539b133b | ||
|
|
0bb52a6058 | ||
|
|
0db40bbb32 | ||
|
|
f66114e203 | ||
|
|
2fcc064b0f | ||
|
|
a4c441a1b7 | ||
|
|
cbb6e4d6f3 | ||
|
|
34361ccd1c | ||
|
|
c953936798 | ||
|
|
6fd2a6ef34 | ||
|
|
be05f1a71f | ||
|
|
0de65d9c0f | ||
|
|
a60f4e3bad | ||
|
|
ab30ea766b | ||
|
|
099a7c46b7 | ||
|
|
a7afcd9644 | ||
|
|
7c80eec755 | ||
|
|
07c50c20b6 | ||
|
|
08d841f6c5 | ||
|
|
6b144c5816 | ||
|
|
322cec0980 | ||
|
|
73a47b2853 | ||
|
|
0036ec2214 | ||
|
|
98dc69893e | ||
|
|
af48af5085 | ||
|
|
0b2279a113 | ||
|
|
ba63a44ec8 | ||
|
|
7c20d2f97c | ||
|
|
8e7369f0b5 | ||
|
|
5f80deb5b7 | ||
|
|
826fdbf342 | ||
|
|
7e5186c3c7 | ||
|
|
2bc5253725 | ||
|
|
f58787bb50 | ||
|
|
88a01d39ee | ||
|
|
ee88897b18 | ||
|
|
b26f9e316d | ||
|
|
0e486b45e1 | ||
|
|
f730d2fc27 | ||
|
|
26303c8617 | ||
|
|
a6485b61a4 | ||
|
|
7db07bca35 | ||
|
|
19bbe0fc1f | ||
|
|
2b2c2de583 | ||
|
|
b05534472c | ||
|
|
30aa8d469c | ||
|
|
c4282a3593 | ||
|
|
778107aae9 | ||
|
|
581af762f9 | ||
|
|
31e63b576b | ||
|
|
efb592dce5 | ||
|
|
fa5b936d7b | ||
|
|
4904bd53ef | ||
|
|
320ce372f5 | ||
|
|
7a803abec8 | ||
|
|
f34407fc43 | ||
|
|
b41bda569d | ||
|
|
fd2919fd1c | ||
|
|
dce8edf742 | ||
|
|
298e32aada | ||
|
|
2b2136867d | ||
|
|
c1830aa37c | ||
|
|
a3d4049c9c | ||
|
|
058b4bbe6c | ||
|
|
c4c7b2ed5b | ||
|
|
aee607ea81 | ||
|
|
5eea5939c0 | ||
|
|
ac53d64ffc | ||
|
|
9ebee8c03e | ||
|
|
93965fd98b | ||
|
|
59c25ef915 | ||
|
|
7e9c4848fb | ||
|
|
467b1ad4f1 | ||
|
|
f45bd18cc2 | ||
|
|
4f844abc0c | ||
|
|
b688dcd4ba | ||
|
|
d5e902679b | ||
|
|
eae21e1371 | ||
|
|
947c2e556d | ||
|
|
d68d4c2c76 | ||
|
|
1ef451c048 | ||
|
|
ec20748594 | ||
|
|
764f05b42a | ||
|
|
5c41e24b99 | ||
|
|
9725091233 | ||
|
|
8f8dfabe0f | ||
|
|
b9749bad61 | ||
|
|
31609a8aba | ||
|
|
28e8cc2675 | ||
|
|
033d3c92ab | ||
|
|
3484fcfd2a | ||
|
|
a8e18d7f99 | ||
|
|
db30b58ee9 | ||
|
|
3748488200 | ||
|
|
c53a20a577 | ||
|
|
dfcb2b610a | ||
|
|
95278a78ff | ||
|
|
400d577546 | ||
|
|
60cf6cec5e | ||
|
|
13901b9028 | ||
|
|
23454a918d | ||
|
|
fa64ecf513 | ||
|
|
bb8c0f1d9c | ||
|
|
6e33e063da | ||
|
|
e44893f91e | ||
|
|
f2c3fc20de | ||
|
|
d903fe400f | ||
|
|
22e4e4125a | ||
|
|
badddfe3d7 | ||
|
|
e14816dcfa | ||
|
|
4b83722a66 | ||
|
|
c798913fd2 | ||
|
|
636dbe5b95 | ||
|
|
ab28d0e09f | ||
|
|
a74efd285c | ||
|
|
3e1eb03517 | ||
|
|
fb90574d44 | ||
|
|
c0fb337dfb | ||
|
|
e7775bb9d9 | ||
|
|
64f2a67573 | ||
|
|
154e33a2c3 | ||
|
|
63ae2b8095 | ||
|
|
6165a6af6c | ||
|
|
4a70e3cd31 | ||
|
|
5ccf053cba | ||
|
|
5a6f5133af | ||
|
|
1a2b4f8260 | ||
|
|
5436050df1 | ||
|
|
d3f3946971 | ||
|
|
597a7f7b40 | ||
|
|
02f549d1dd | ||
|
|
0c096bb090 | ||
|
|
8bc6cd7fc9 | ||
|
|
65d9e5d1fc | ||
|
|
47c356692f | ||
|
|
ef9157174c | ||
|
|
7345807871 | ||
|
|
19b9d3737e | ||
|
|
db3be3d80a | ||
|
|
60c7522f22 | ||
|
|
60002793b0 | ||
|
|
9e5a4189d7 | ||
|
|
945cbdd3a7 | ||
|
|
f974fd0660 | ||
|
|
af9fdfa224 | ||
|
|
77c72d2bb3 | ||
|
|
8404617090 | ||
|
|
cc9a429689 | ||
|
|
44f50eba5b | ||
|
|
f4509e24c6 | ||
|
|
e17a40fdb2 | ||
|
|
181cb235df | ||
|
|
e3456cb74f | ||
|
|
e377552f12 | ||
|
|
9ab9e4894d | ||
|
|
5782979203 | ||
|
|
a4bb279da8 | ||
|
|
8df9549a42 | ||
|
|
de873c5f6f | ||
|
|
3425e929e9 | ||
|
|
60c5d96037 | ||
|
|
4b4c3ddb2f | ||
|
|
1ea50ea917 | ||
|
|
29f68d218d | ||
|
|
daad8bca69 | ||
|
|
f4408aa72c | ||
|
|
0117cd478b | ||
|
|
9ad22d7405 | ||
|
|
de4d0989e9 | ||
|
|
0c884c2669 | ||
|
|
5d7cfc1c10 | ||
|
|
fd2b070a6a | ||
|
|
455819566b | ||
|
|
b39113f0ae | ||
|
|
af0f1939a3 | ||
|
|
becb9fc43e | ||
|
|
8b9c274fdd | ||
|
|
0701f3496b | ||
|
|
09c03e8ca7 | ||
|
|
9285da6c12 | ||
|
|
6a0e16885d | ||
|
|
f0db135b1d | ||
|
|
4fb86bd699 | ||
|
|
c62082b924 | ||
|
|
e8f592c6e0 | ||
|
|
61935942cf | ||
|
|
f1d8bb84b7 | ||
|
|
7918448be2 | ||
|
|
f89f704a69 | ||
|
|
ae33de7e7c | ||
|
|
b23e474648 | ||
|
|
611bc26685 | ||
|
|
0dc39166ac | ||
|
|
8d970b7858 | ||
|
|
7033c4a182 | ||
|
|
2c0ca78265 | ||
|
|
0d3c03d1e3 | ||
|
|
b4dfce4a44 | ||
|
|
91ca3939b3 | ||
|
|
92db5d3a35 | ||
|
|
f252960aaf | ||
|
|
4aec39df7a | ||
|
|
15b19925f2 | ||
|
|
bfb376505b | ||
|
|
ec75ff5292 | ||
|
|
28eb0be4ad | ||
|
|
4d3b6b1486 | ||
|
|
d3fd9a188d | ||
|
|
41a15f90cb | ||
|
|
9c604a7886 | ||
|
|
8ad1d6fd97 | ||
|
|
a18e7eb089 | ||
|
|
1f5ea40bf6 | ||
|
|
44509e027c | ||
|
|
fe3758b1bb | ||
|
|
ebe2a30463 | ||
|
|
1216a26d13 | ||
|
|
65800853f4 | ||
|
|
ccb81179ab | ||
|
|
f2ea701d34 | ||
|
|
1d4aa27f1c | ||
|
|
bb08fe8113 | ||
|
|
e2099f0749 | ||
|
|
3c60feed02 | ||
|
|
5466e1b733 | ||
|
|
328f15c2ea | ||
|
|
873125abe1 | ||
|
|
5df818a19c | ||
|
|
a5dc3cd018 | ||
|
|
afe0e3c1d6 | ||
|
|
91e1f958f2 | ||
|
|
2a94ee55cc | ||
|
|
ccf612f536 | ||
|
|
c6fa0cc072 | ||
|
|
c282bb2fe1 | ||
|
|
72d18fd7e1 | ||
|
|
6802873cd1 | ||
|
|
1bdc46969c | ||
|
|
989ee0e281 | ||
|
|
0f27d646bb | ||
|
|
81aca500b3 | ||
|
|
50f2dded64 | ||
|
|
d26d94b62a | ||
|
|
2811f76714 | ||
|
|
67b21ad766 | ||
|
|
6d07d5dccb | ||
|
|
da0e3d5c8b | ||
|
|
b129fe908c | ||
|
|
f5c57e84c7 | ||
|
|
ceb4ef2642 | ||
|
|
1c235aa761 | ||
|
|
cfc8117c3c | ||
|
|
aa1f515fcf | ||
|
|
4fdd12bc48 | ||
|
|
34f04b1946 | ||
|
|
5770b9dc0e | ||
|
|
afe2b934de | ||
|
|
11fe6cfbb0 | ||
|
|
db10226005 | ||
|
|
a15b8077a3 | ||
|
|
a3836b5e17 | ||
|
|
f8d80422b2 | ||
|
|
9848f80630 | ||
|
|
6ea1732630 | ||
|
|
d97571ce0c | ||
|
|
1e3b866c8b | ||
|
|
2168838365 | ||
|
|
219021873d | ||
|
|
120b505361 | ||
|
|
347a2977fa | ||
|
|
c2e90864ac | ||
|
|
1027efd6e5 | ||
|
|
bd0de83d31 | ||
|
|
4d3523b677 | ||
|
|
03f15e0075 | ||
|
|
043779f4af | ||
|
|
25b5daf6a5 | ||
|
|
db444f5d7e | ||
|
|
16499d2fb8 | ||
|
|
ddff2b2982 | ||
|
|
e697ee72fa | ||
|
|
f98c59172b | ||
|
|
3badafaa82 | ||
|
|
cbf65a9355 | ||
|
|
365bc900b0 | ||
|
|
bd0da63f4c | ||
|
|
db0b663a3d | ||
|
|
fd7fe129e2 | ||
|
|
27253c360b | ||
|
|
ab226d16c8 | ||
|
|
d6394402b8 | ||
|
|
6be5fac953 | ||
|
|
c4435279de | ||
|
|
a9bdc8ad85 | ||
|
|
df2a5fc789 | ||
|
|
db87f9e15b | ||
|
|
5af2768d33 | ||
|
|
474695643f | ||
|
|
97ab88b39a | ||
|
|
3773d40201 | ||
|
|
b3fd01fe04 | ||
|
|
75c4ca77c2 | ||
|
|
692ddc60c7 | ||
|
|
1a296a8ca1 | ||
|
|
f5595dd4c3 | ||
|
|
11c0221f81 | ||
|
|
2d0aad3da9 | ||
|
|
ff19cb68b4 | ||
|
|
e62df3b3b1 | ||
|
|
1d024cc339 | ||
|
|
8bda91aafb | ||
|
|
fd9963e7eb | ||
|
|
dc81ca4f53 | ||
|
|
fb754f9bc7 | ||
|
|
7045f6571f | ||
|
|
50d9bccacf | ||
|
|
9064769185 | ||
|
|
5fc16bdbfb | ||
|
|
172e4e939d | ||
|
|
f914b728ff | ||
|
|
54857e843b | ||
|
|
64b34e98c7 | ||
|
|
1ccf74bca1 | ||
|
|
49a534a61b | ||
|
|
b8889c6a1f | ||
|
|
ccbc5c9d17 | ||
|
|
555e01ec87 | ||
|
|
7869f472c3 | ||
|
|
90f60f95f7 | ||
|
|
0f0a71a109 | ||
|
|
a43c8a2def | ||
|
|
cbafaf5d56 | ||
|
|
62e4e13f5a | ||
|
|
e69908abef | ||
|
|
6cb3cf8747 | ||
|
|
2f71a43420 | ||
|
|
f57ad57e62 | ||
|
|
03f5d9b102 | ||
|
|
6b17e1820c | ||
|
|
e0f6fca987 | ||
|
|
1fe95a5fe4 | ||
|
|
1257ecf100 | ||
|
|
4163304b24 | ||
|
|
d35f2c4a4f | ||
|
|
e5d5c5f9a7 | ||
|
|
6fcaec3ca8 | ||
|
|
a2892ad097 | ||
|
|
79c79146a5 | ||
|
|
cd37ba308c | ||
|
|
b35c0f7e39 | ||
|
|
14b1b649cb | ||
|
|
14c0307c09 | ||
|
|
42f22119f2 | ||
|
|
75f4771616 | ||
|
|
83f7cb2033 | ||
|
|
43a4c6198c | ||
|
|
8c2fafecd7 | ||
|
|
d004c0ccd1 | ||
|
|
406ae4e8c3 | ||
|
|
cd8bee1371 | ||
|
|
123392c549 | ||
|
|
42ffe213fd | ||
|
|
fd738e5c8b | ||
|
|
6f95b2c2ad | ||
|
|
f66c2b078c | ||
|
|
c6f5c120ba | ||
|
|
677e93430d | ||
|
|
a9a90c5545 | ||
|
|
ee0418e719 | ||
|
|
6fc1141477 | ||
|
|
b02920c43c | ||
|
|
049d249609 | ||
|
|
fc2a554415 | ||
|
|
42b806b500 | ||
|
|
aeb3ccaf09 | ||
|
|
86fdd91597 | ||
|
|
e68fea185d | ||
|
|
a3eaf9f473 | ||
|
|
e6a2b9f06e | ||
|
|
a78973702b | ||
|
|
354b745c39 | ||
|
|
ce6cd6acdc | ||
|
|
8e129143f1 | ||
|
|
6d50cbba6f | ||
|
|
7731878f36 | ||
|
|
9f659eef1b | ||
|
|
14cc642e54 | ||
|
|
c47852cd0a | ||
|
|
c3bfaa31ee | ||
|
|
832505a315 | ||
|
|
cb71667336 | ||
|
|
1032e97d58 | ||
|
|
b4271da13e | ||
|
|
e2dc5ef4f2 | ||
|
|
c75ee042a8 | ||
|
|
d474d518ca | ||
|
|
52b8dbcbb1 | ||
|
|
0d8d8f0426 | ||
|
|
ed12deae25 | ||
|
|
7f1e7c981d | ||
|
|
cc26688d82 | ||
|
|
a0fa3a6063 | ||
|
|
110a1a640d | ||
|
|
bbdc43c750 | ||
|
|
c73b9b4882 | ||
|
|
e249092f91 | ||
|
|
5c0b04bfc8 | ||
|
|
bc257f4951 | ||
|
|
e738ee0812 | ||
|
|
ebb2db17f3 | ||
|
|
4214293b76 | ||
|
|
ce3ee909bf | ||
|
|
09ba1e2470 | ||
|
|
68444b81cc | ||
|
|
d3c0b9a438 | ||
|
|
6e2f1f72c6 | ||
|
|
c82eec09b7 | ||
|
|
d4093d8c98 | ||
|
|
90616c82b6 | ||
|
|
de69fe1745 | ||
|
|
9bd42ac221 | ||
|
|
2f9a272696 | ||
|
|
552ea0356e | ||
|
|
ff6bd91ef7 | ||
|
|
835f20f872 | ||
|
|
1e9b35d18f | ||
|
|
3818e48218 | ||
|
|
5d63065057 | ||
|
|
ae41ed1d51 | ||
|
|
36ead2251a | ||
|
|
dc7093f68a | ||
|
|
6c79d2b008 | ||
|
|
422349c2d1 | ||
|
|
7dbfa0b203 | ||
|
|
57ea2ac039 | ||
|
|
a9e664e89d | ||
|
|
c0e2210da3 | ||
|
|
b13c6f283a | ||
|
|
8181b9a31c | ||
|
|
105e4f990d | ||
|
|
9670d74345 | ||
|
|
86e553e756 | ||
|
|
566ea9a110 | ||
|
|
f59f035a7e | ||
|
|
4c6d4f3caf | ||
|
|
8af87bac22 | ||
|
|
690567659c | ||
|
|
d9c7ee8976 | ||
|
|
95cf554de4 | ||
|
|
47a87a14f5 | ||
|
|
5e860b6850 | ||
|
|
9a983e7565 | ||
|
|
00197d131d | ||
|
|
9758f3c9d2 | ||
|
|
e7d7425b6e | ||
|
|
b566c81ae7 | ||
|
|
742837e7a1 | ||
|
|
5087dbd756 | ||
|
|
b893ae7c14 | ||
|
|
1f7863057f | ||
|
|
3dd3afd21f | ||
|
|
387d3b7335 | ||
|
|
782bfd058b | ||
|
|
c0d936fa4d | ||
|
|
63819c5757 | ||
|
|
08cbac6277 | ||
|
|
68c0a9aec4 | ||
|
|
1c585815a1 | ||
|
|
853ec7320f | ||
|
|
b8917a3c0e | ||
|
|
c4d70e7f9b | ||
|
|
7f1b11d19b | ||
|
|
02a32dea40 | ||
|
|
d9e20ea17a | ||
|
|
039c2fe0a6 | ||
|
|
a967e73f9e | ||
|
|
222e4154a1 | ||
|
|
56413ee94e | ||
|
|
93c07b2b1e | ||
|
|
27ed64a1af | ||
|
|
ad68106c3c | ||
|
|
a591cf1d21 | ||
|
|
03a4b8f5cf | ||
|
|
2d8d25808d | ||
|
|
a82fcce734 | ||
|
|
0734e136d0 | ||
|
|
2913120ff7 | ||
|
|
bd277b087a | ||
|
|
fc00966b8b | ||
|
|
495a76353f | ||
|
|
6ea225ed2a | ||
|
|
c1a5f59c42 | ||
|
|
49fb9108e9 | ||
|
|
4cb3b514ab | ||
|
|
c95a37130a | ||
|
|
29e82cc509 | ||
|
|
a4cb53fdb4 | ||
|
|
865dce6f68 | ||
|
|
1d02154d99 | ||
|
|
3a8d72db31 | ||
|
|
ec57a240d5 | ||
|
|
949f7587dc | ||
|
|
55cce646e0 | ||
|
|
4c3dce694a | ||
|
|
46d5b70391 | ||
|
|
08a102d182 | ||
|
|
1cf8e08d4b | ||
|
|
65a8b83150 | ||
|
|
f4c8db654c | ||
|
|
5c4d1c0259 | ||
|
|
a459f8b84c | ||
|
|
0d672420f7 | ||
|
|
2f7be0559a | ||
|
|
0623ae1f87 | ||
|
|
8ae946c2c5 | ||
|
|
bb75f6ffce | ||
|
|
fcfe83f0cc | ||
|
|
5cbcded929 | ||
|
|
2a95f792ec | ||
|
|
daa2808448 | ||
|
|
fc06ffdcee | ||
|
|
1601179081 | ||
|
|
7fe374b67e | ||
|
|
7a353bbe48 | ||
|
|
c103ff271b | ||
|
|
ab9e0f891a | ||
|
|
af85ef8cfb | ||
|
|
3cea6e5d0c | ||
|
|
6d1b0ae498 | ||
|
|
07d5b07748 | ||
|
|
d47b9cd5c0 | ||
|
|
d542c063d7 | ||
|
|
4bb3d33907 | ||
|
|
62bec25b6e | ||
|
|
3ba16f1773 | ||
|
|
c302030301 | ||
|
|
49abe2b11f | ||
|
|
544e7fce88 | ||
|
|
b9e7f018e2 | ||
|
|
f31049cf69 | ||
|
|
2b3b73b3f1 | ||
|
|
704bb5a848 | ||
|
|
01f7d7add2 | ||
|
|
831d8b6d36 | ||
|
|
2e9b6ead2e | ||
|
|
d71fd0ff2d | ||
|
|
6466bd4ba7 | ||
|
|
a97fa1abb6 | ||
|
|
6171e5cc6e | ||
|
|
456502893c | ||
|
|
443a90c7ba | ||
|
|
b8a72245dc | ||
|
|
d019f88e26 | ||
|
|
01cf4cc1ed | ||
|
|
396bbd83c8 | ||
|
|
92e0affb85 | ||
|
|
6552157894 | ||
|
|
af41e4892f | ||
|
|
09531b399a | ||
|
|
6251b77b28 | ||
|
|
0099b6d4a2 | ||
|
|
adb8de9754 | ||
|
|
8ac8b666bf | ||
|
|
095feddf73 | ||
|
|
4882a801d2 | ||
|
|
1a1736ca0e | ||
|
|
a7619771a6 | ||
|
|
6febcf3b94 | ||
|
|
3947deb7bd | ||
|
|
98855de71f | ||
|
|
8010e6220d | ||
|
|
09e6a6a4ad | ||
|
|
da772e6649 | ||
|
|
65b8f78ca1 | ||
|
|
23bcac2e55 | ||
|
|
e6a88eef35 | ||
|
|
6654c461a6 | ||
|
|
a48cb052c2 | ||
|
|
809d932087 | ||
|
|
19d906c5e4 | ||
|
|
2f933a90fd | ||
|
|
3607875714 | ||
|
|
fec8829041 | ||
|
|
f58e758a41 | ||
|
|
cebed0824f | ||
|
|
97120bd1f1 | ||
|
|
4237d0c7e3 | ||
|
|
243cdfefa2 | ||
|
|
a12a4cd8f2 | ||
|
|
980b8a2924 | ||
|
|
989dca5792 | ||
|
|
c9eb06bb70 | ||
|
|
af89906b81 | ||
|
|
de71b1b397 | ||
|
|
2decee1d87 | ||
|
|
6a184b069b | ||
|
|
48db615ac8 | ||
|
|
bb9caa4838 | ||
|
|
3c11c3fc16 | ||
|
|
6c1dbc5e61 | ||
|
|
21bf1dd1a3 | ||
|
|
78aa2b491c | ||
|
|
53d2c7e89f | ||
|
|
cdf78db629 | ||
|
|
15c5725829 | ||
|
|
96653170a2 | ||
|
|
eade89da48 | ||
|
|
9b86049964 | ||
|
|
9e2bbd50b6 | ||
|
|
0d18266ad1 | ||
|
|
83ee0534f2 | ||
|
|
8ad00025ad | ||
|
|
7d08a7c9cd | ||
|
|
c8d5a5319e | ||
|
|
a08fa721cf | ||
|
|
89bc3137ba | ||
|
|
4d8d30f897 | ||
|
|
d67e9468c0 | ||
|
|
7dda36ab97 | ||
|
|
32df3e80b1 | ||
|
|
3c33969d23 | ||
|
|
c2aec5ae36 | ||
|
|
7afc908c32 | ||
|
|
c66ecbdd29 | ||
|
|
e61bccab36 | ||
|
|
cfeef98261 | ||
|
|
c949548150 | ||
|
|
829ccfca88 | ||
|
|
950fa84d1c | ||
|
|
5666729fcf | ||
|
|
3a13886af9 | ||
|
|
db6e0ccf63 | ||
|
|
35f2ebc2aa | ||
|
|
60ac4a3e86 | ||
|
|
c966d34b07 | ||
|
|
a05d7059fb | ||
|
|
facc1dc944 | ||
|
|
df2ebbf384 | ||
|
|
e210471c7a | ||
|
|
f42d552dad | ||
|
|
edfd9e46b6 | ||
|
|
27644776f3 | ||
|
|
a4797dcc73 | ||
|
|
677312648b | ||
|
|
ace460c69b | ||
|
|
b922fe35ab | ||
|
|
222e2166ff | ||
|
|
7dc25ec425 | ||
|
|
980835981f | ||
|
|
e425adc230 | ||
|
|
2ea7ef327e | ||
|
|
6c9d33f05c | ||
|
|
c584b51726 | ||
|
|
3c8fa3382b | ||
|
|
e5c75259e0 | ||
|
|
f78e437a42 | ||
|
|
8f61b1d320 | ||
|
|
84f3c6f7e6 | ||
|
|
bfb6c001a0 | ||
|
|
f0fa9f2033 | ||
|
|
c82cc30968 | ||
|
|
b0cb14b515 | ||
|
|
7f86d2aa0a | ||
|
|
482dd4db76 | ||
|
|
0f44fd2290 | ||
|
|
690d461693 | ||
|
|
f1ca72aee9 | ||
|
|
a3a6fc0d15 | ||
|
|
4f4fe5f06b | ||
|
|
c59f47f4b5 | ||
|
|
0ae810b8c6 | ||
|
|
ac9f42a8fe | ||
|
|
eab7e56ece | ||
|
|
7329515a4d | ||
|
|
6d6bf2df3a | ||
|
|
3008bfbe0a | ||
|
|
9399517cfb | ||
|
|
b117fe222d | ||
|
|
62567264f0 | ||
|
|
c054b3b0de | ||
|
|
83fb5b4d1b | ||
|
|
07a86800c9 | ||
|
|
688b5f29b6 | ||
|
|
e311f17062 | ||
|
|
b4cdb22e24 | ||
|
|
b63194c0aa | ||
|
|
0bab32315c | ||
|
|
7e881dd850 | ||
|
|
d6aaafb069 | ||
|
|
731fcb8829 | ||
|
|
af0e94a4b7 | ||
|
|
deda869cc5 | ||
|
|
434089395a | ||
|
|
048985bdf4 | ||
|
|
70d6d4246d | ||
|
|
70befe900c | ||
|
|
9fd81bf6c7 | ||
|
|
a388fe3acb | ||
|
|
d4946d931a | ||
|
|
9812654bfa | ||
|
|
557426246c | ||
|
|
d0a3e8f789 | ||
|
|
50b37f2ddd | ||
|
|
e4197012f6 | ||
|
|
df00a1e0a3 | ||
|
|
41327bfb03 | ||
|
|
66ef72a040 | ||
|
|
af660bc631 | ||
|
|
18edb13e76 | ||
|
|
e05431c847 | ||
|
|
5c61f95093 | ||
|
|
9a407c727a | ||
|
|
cad655a15b | ||
|
|
1fa5c53b72 | ||
|
|
d01b1a706c | ||
|
|
678d5fc532 | ||
|
|
c4e01fa566 | ||
|
|
e694622b83 | ||
|
|
1d16c96ca4 | ||
|
|
ab1f34726b | ||
|
|
c9f201755e | ||
|
|
094ef592a7 | ||
|
|
e7493c38d1 | ||
|
|
6fd0fcfdb5 | ||
|
|
6da534a961 | ||
|
|
f26e43144e | ||
|
|
427529171c | ||
|
|
cd146cf822 | ||
|
|
ced412372c | ||
|
|
2f6e650c1b | ||
|
|
5c125ca9b4 | ||
|
|
89c0939d58 | ||
|
|
8ea955fb23 | ||
|
|
73a297f23f | ||
|
|
95f1382fbf | ||
|
|
80df01c8ee | ||
|
|
c2df864119 | ||
|
|
2cc9356c32 | ||
|
|
89234c0163 | ||
|
|
1b7fe286a6 | ||
|
|
7c2d797ed0 | ||
|
|
4d2eedc56b | ||
|
|
ece0d9301f | ||
|
|
cc10cd88d3 | ||
|
|
b9f308c832 | ||
|
|
6816bd8bad | ||
|
|
0e026de5bd | ||
|
|
a419ad201d | ||
|
|
a66a4f62bd | ||
|
|
e721d2204b | ||
|
|
f293cf6e81 | ||
|
|
0cde1d4969 | ||
|
|
bd49bd6e33 | ||
|
|
84dc1fa151 | ||
|
|
5858e862d9 | ||
|
|
8b004a549a | ||
|
|
4a53e4207c | ||
|
|
6510de5d29 | ||
|
|
a6191320a1 | ||
|
|
a75ff0c061 | ||
|
|
0d45eb91db | ||
|
|
95edbc16bb | ||
|
|
15a5e3c779 | ||
|
|
0433432e62 | ||
|
|
e7ca73bbad | ||
|
|
8d8374b8e2 | ||
|
|
4dc5bbe601 | ||
|
|
55371f9c78 | ||
|
|
af63f4098f | ||
|
|
2b4939a875 | ||
|
|
d5d22844ab | ||
|
|
7dab00be87 | ||
|
|
67582d388a | ||
|
|
0671e7d456 | ||
|
|
c9e6af96d0 | ||
|
|
ee48a56603 | ||
|
|
4c03f39437 | ||
|
|
d8d425c963 | ||
|
|
ec64ac9f1d | ||
|
|
7ed682c186 | ||
|
|
9dcb579741 | ||
|
|
19f837aa41 | ||
|
|
b267491934 | ||
|
|
a369dddde8 | ||
|
|
29d87d7c48 | ||
|
|
4847f50093 | ||
|
|
7c848b1253 | ||
|
|
607aa46032 | ||
|
|
430193891f | ||
|
|
cbb82ed635 | ||
|
|
1dfb72703a | ||
|
|
5edf377f4b | ||
|
|
43a33d267a | ||
|
|
c4048f4c7b | ||
|
|
501c89ae3a | ||
|
|
5899497aa7 | ||
|
|
2c758a9981 | ||
|
|
66eb99e506 | ||
|
|
b583140077 | ||
|
|
f378c93dd3 | ||
|
|
5d29fa5e62 | ||
|
|
54f04c9141 | ||
|
|
fc0c706100 | ||
|
|
02ac9fa0d7 | ||
|
|
ca95c75df3 | ||
|
|
4ff86795b9 | ||
|
|
30eaec29d3 | ||
|
|
742d38c9ec | ||
|
|
56a4597784 | ||
|
|
b2a7d3584b | ||
|
|
b8167f89e5 | ||
|
|
c916472b22 | ||
|
|
bdfe7c5e69 | ||
|
|
749475799a | ||
|
|
daf9c807b5 | ||
|
|
5dfecfdee3 | ||
|
|
d267c03ee2 | ||
|
|
864e3c7a50 | ||
|
|
747e1a818d | ||
|
|
f468dbf427 | ||
|
|
88572e90d4 | ||
|
|
41fc7dd73d | ||
|
|
c87c588c79 | ||
|
|
5ab4b57411 | ||
|
|
3c936c6957 | ||
|
|
0ca903a146 | ||
|
|
4e91919990 | ||
|
|
e023a68780 | ||
|
|
17452cd5b6 | ||
|
|
c76f2c8483 | ||
|
|
90207f9b68 | ||
|
|
0ec5371b61 | ||
|
|
8549aeb466 | ||
|
|
504d3cd131 | ||
|
|
83ed298eba | ||
|
|
a90f2cb156 | ||
|
|
1a54bafdd5 | ||
|
|
3cc186f7e4 | ||
|
|
a2497d7564 | ||
|
|
c01c882081 | ||
|
|
af279df5c9 | ||
|
|
1ea7ce2589 | ||
|
|
476c577bc1 | ||
|
|
e3b91c4d71 | ||
|
|
1e2d7acf4a | ||
|
|
1def120616 | ||
|
|
25ddf2c651 | ||
|
|
e5d384e808 | ||
|
|
63351553d8 | ||
|
|
4630740ac7 | ||
|
|
0ff4884d3a | ||
|
|
2dfdedf7b0 | ||
|
|
e1fa5fb180 | ||
|
|
4e47f9eb68 | ||
|
|
c4c8955bc2 | ||
|
|
f47b808478 | ||
|
|
493367da5e | ||
|
|
4ca185cf45 | ||
|
|
8f4effbb8d | ||
|
|
a4ba7f277e | ||
|
|
c3f97a0cf1 | ||
|
|
c1b8fc1233 | ||
|
|
a481638c03 | ||
|
|
c12dfc7b4d | ||
|
|
34bc527709 | ||
|
|
ee134d0d7c | ||
|
|
f795ee7fd9 | ||
|
|
1bba75881f | ||
|
|
34db2d9efa | ||
|
|
91dd308952 | ||
|
|
3d97e26cde | ||
|
|
104c1ecbec | ||
|
|
88266ec4e3 | ||
|
|
f5be159187 | ||
|
|
1194d86460 | ||
|
|
76d6dca63f | ||
|
|
1b69e62e2e | ||
|
|
e89839359f | ||
|
|
177d113cd9 | ||
|
|
853fa87012 | ||
|
|
a592ca25ff | ||
|
|
a8c9926fa7 | ||
|
|
bf5587fe09 | ||
|
|
7c8a27e894 | ||
|
|
d248b11ffc | ||
|
|
1282e010ee | ||
|
|
d5d1ca948e | ||
|
|
a08704e8ed | ||
|
|
2a8c0c0c08 | ||
|
|
2ae0c98b4c | ||
|
|
c427050a92 | ||
|
|
43a0829f44 | ||
|
|
e9b8b91861 | ||
|
|
6f104f5056 | ||
|
|
e720efabdc | ||
|
|
45cb770e41 | ||
|
|
3f1cc66767 | ||
|
|
d1f5118bb5 | ||
|
|
b90f1f786e | ||
|
|
c6f424201b | ||
|
|
a7db8cf7cd | ||
|
|
e2ed0f5e55 | ||
|
|
d000e3c8a9 | ||
|
|
cf465a1184 | ||
|
|
f3119824f4 | ||
|
|
ef069c1689 | ||
|
|
68e5a9dfda | ||
|
|
fd1a31afb6 | ||
|
|
6d7d4a15d9 | ||
|
|
518a7d0dcc | ||
|
|
a4bdfe6b7d | ||
|
|
281269aa0d | ||
|
|
33521ebd31 | ||
|
|
18ae08de8f | ||
|
|
3d3c4ba02f | ||
|
|
89917c1582 | ||
|
|
90c6758562 | ||
|
|
5be8084473 | ||
|
|
8a066a4ec0 | ||
|
|
b98237fa44 | ||
|
|
c4f9388668 | ||
|
|
0f44b27e54 | ||
|
|
10d05e1870 | ||
|
|
921557161d | ||
|
|
eb092b9f20 | ||
|
|
28ca8a9f9f | ||
|
|
d7be56df7a | ||
|
|
ce2c163f4b | ||
|
|
5272462368 | ||
|
|
42354a6728 | ||
|
|
754fe3df91 | ||
|
|
a7a0350c1a | ||
|
|
a8b2ca7cfe | ||
|
|
e82867820b | ||
|
|
13305d111e | ||
|
|
ae37fa2bc5 | ||
|
|
c81db752f6 | ||
|
|
5d9d71dee8 | ||
|
|
1f558d46a4 | ||
|
|
36eb899c3b | ||
|
|
e223d752cb | ||
|
|
fcb503e885 | ||
|
|
c1055234d8 | ||
|
|
35ec98cf13 | ||
|
|
66a9138666 | ||
|
|
279582ff21 | ||
|
|
a9540ffabe | ||
|
|
8f02cb83ed | ||
|
|
5e94c8be7b | ||
|
|
ea6e9af5da | ||
|
|
1bb72262ba | ||
|
|
61ace7bd97 | ||
|
|
1a417cc36f | ||
|
|
00a11f4343 | ||
|
|
491bbacddd | ||
|
|
1b9daa0adb | ||
|
|
ccdc981756 | ||
|
|
b44dcc9f30 | ||
|
|
479ceb14e4 | ||
|
|
50e41d1999 | ||
|
|
f6e2073de0 | ||
|
|
271aab9746 | ||
|
|
8d9bf5cf17 | ||
|
|
ceb7ed093e | ||
|
|
abdbcbb741 | ||
|
|
51ac07cd34 | ||
|
|
4b29698c6c | ||
|
|
f93285846a | ||
|
|
44347db52e | ||
|
|
f2749ff17f | ||
|
|
3735342dfa | ||
|
|
fed6e1e82f | ||
|
|
58a59b624a | ||
|
|
1338918a89 | ||
|
|
831e7cdb3f | ||
|
|
2b8583e652 | ||
|
|
b0220e4200 | ||
|
|
0d94ef10ce | ||
|
|
544a1381fc | ||
|
|
bc17ef896e | ||
|
|
0bcbf999fb | ||
|
|
0c4c44f4b6 | ||
|
|
486956b762 | ||
|
|
8d1ef5291f | ||
|
|
611627ca97 | ||
|
|
732225b781 | ||
|
|
58f88075c8 | ||
|
|
e17ef5eccf | ||
|
|
70c697f094 | ||
|
|
4b5625e0b4 | ||
|
|
7df48870df | ||
|
|
4a309c49e5 | ||
|
|
b45899bf90 | ||
|
|
5ae3c8acfe | ||
|
|
ef5df5f01b | ||
|
|
9af7451a61 | ||
|
|
7048c550b7 | ||
|
|
f035627f42 | ||
|
|
7659ff1f77 | ||
|
|
3df4062a55 | ||
|
|
02bbbe668b | ||
|
|
2b82c8fdc9 | ||
|
|
93abaed0c2 | ||
|
|
b7fff6d452 | ||
|
|
d09f01db90 | ||
|
|
e0c1a58b84 | ||
|
|
1b82649cca | ||
|
|
9317e2a36b | ||
|
|
51aff8ccdc | ||
|
|
bdd3ea45af | ||
|
|
3eb5c77ac4 | ||
|
|
ccc85784c6 | ||
|
|
46806e8607 | ||
|
|
95f914d6bd | ||
|
|
0f86011106 | ||
|
|
acdd3c0602 | ||
|
|
05b7237add | ||
|
|
51f4e9e160 | ||
|
|
7bbac35d6b | ||
|
|
d280fe457c | ||
|
|
b5772af4c3 | ||
|
|
7ab79bb76e | ||
|
|
00e3cc26de | ||
|
|
4b491c43ff | ||
|
|
41233a933e | ||
|
|
b84e553d34 | ||
|
|
19b9fa1996 | ||
|
|
6abdc4172b | ||
|
|
5e0c0137d3 | ||
|
|
3e468d1348 | ||
|
|
051af521b2 | ||
|
|
19b6ad3568 | ||
|
|
5ae514e9b8 | ||
|
|
826ee98165 | ||
|
|
f4c021a634 | ||
|
|
717ae1903e | ||
|
|
3cd7cdd4fb | ||
|
|
ff612799c0 | ||
|
|
d364b04cad | ||
|
|
212aef79aa | ||
|
|
9ca2b08a0e | ||
|
|
fc3ac88806 | ||
|
|
c550c4c212 | ||
|
|
f0df8a4a09 | ||
|
|
65923abcae | ||
|
|
c4f3009bb5 | ||
|
|
405a81c8f0 | ||
|
|
7a067a0f6e | ||
|
|
32c9f197b1 | ||
|
|
85151b23d3 | ||
|
|
fc0a4d90df | ||
|
|
9558616f59 | ||
|
|
5be5741ac3 | ||
|
|
80c0e6a4e0 | ||
|
|
9bc8f54233 | ||
|
|
a4c02cef54 | ||
|
|
935f4132ab | ||
|
|
a1cb82e7db | ||
|
|
146d782729 | ||
|
|
ac8bf5e939 | ||
|
|
2a70620844 | ||
|
|
7494b867a7 | ||
|
|
2874ee8609 | ||
|
|
e61145eabe | ||
|
|
4f01c574d2 | ||
|
|
06a471033c | ||
|
|
3761bfd26f | ||
|
|
07ad1b1de4 | ||
|
|
5725af55a8 | ||
|
|
d0f75ffda9 | ||
|
|
4117938140 | ||
|
|
f50c206d4f | ||
|
|
ed95cb791c | ||
|
|
9d0bf6d409 | ||
|
|
5e68a8200d | ||
|
|
15887994fe | ||
|
|
8bec8281d2 | ||
|
|
2e5a5812a9 | ||
|
|
744f9316a9 | ||
|
|
a6da9e8943 | ||
|
|
14d3bb273c | ||
|
|
37f8c0783d | ||
|
|
05a946e2bf | ||
|
|
a1b3e0778a | ||
|
|
93f8ade350 | ||
|
|
2a3a942b8e | ||
|
|
796583c0be | ||
|
|
df31b56cf3 | ||
|
|
e5f4446c82 | ||
|
|
0252495eca | ||
|
|
5e75a6b4a0 | ||
|
|
3002a4f9b3 | ||
|
|
f627c5e5a1 | ||
|
|
4d0a93fc3b | ||
|
|
3f040e7744 | ||
|
|
e572d544ef | ||
|
|
ab3f585a2b | ||
|
|
8b792c5fe0 | ||
|
|
f184116824 | ||
|
|
ab2c91ba20 | ||
|
|
f2a786254e | ||
|
|
7cbc8a0ede | ||
|
|
08bc644de1 | ||
|
|
f12125f2a4 | ||
|
|
4e86de7fc2 | ||
|
|
38796a0d40 | ||
|
|
8562bdfc4a | ||
|
|
74c96d8521 | ||
|
|
5f8ef64ca4 | ||
|
|
5a5f5318d1 | ||
|
|
db9e615e4d | ||
|
|
2aae0528b5 | ||
|
|
8d29bd5c32 | ||
|
|
77cb8530e5 | ||
|
|
bfd7404c85 | ||
|
|
836148a335 | ||
|
|
1ab00ac804 | ||
|
|
7a3db8f670 | ||
|
|
fd3676067a | ||
|
|
de61e4bf8c | ||
|
|
3d0de834e0 | ||
|
|
a897772df2 | ||
|
|
5726d796f9 | ||
|
|
8381960737 | ||
|
|
b61d41f569 | ||
|
|
af827b5645 | ||
|
|
13a01d76f7 | ||
|
|
2007f5ece4 | ||
|
|
a91a2c2609 | ||
|
|
0890fd521e | ||
|
|
4338cb305d | ||
|
|
84e02c828f | ||
|
|
be8707570c | ||
|
|
39602e0a98 | ||
|
|
bc2f2f5323 | ||
|
|
66e71282a0 | ||
|
|
bca56f88af | ||
|
|
35068631ec | ||
|
|
bd9557b11e | ||
|
|
0f2c19f40f | ||
|
|
4248ae7792 | ||
|
|
535a4205b1 | ||
|
|
ab14fc8440 | ||
|
|
86eea16271 | ||
|
|
52a9caa96e | ||
|
|
d8fe1a6e44 | ||
|
|
ae86090a03 | ||
|
|
87aa887b2f | ||
|
|
81378b5e25 | ||
|
|
6f615b8202 | ||
|
|
44c1266a8c | ||
|
|
920f720699 | ||
|
|
a7c394de6c | ||
|
|
4529675ca6 | ||
|
|
935909f24b | ||
|
|
7b61a0253c | ||
|
|
64e039cf8f | ||
|
|
65ae1f6f5a | ||
|
|
fa38ad3a74 | ||
|
|
fd500ac411 | ||
|
|
c6b5bb84e9 | ||
|
|
3b1f1a41dc | ||
|
|
d778f2dd8b | ||
|
|
287452169b | ||
|
|
6fdcd7f7e9 | ||
|
|
b16a49109f | ||
|
|
7d8cde2f0f | ||
|
|
a3fedb47cb | ||
|
|
095f08d443 | ||
|
|
a7948ee1da | ||
|
|
54eeb27f09 | ||
|
|
d0e57df1d8 | ||
|
|
b4df63f37f | ||
|
|
16a7ea2b75 | ||
|
|
3892ce3ed4 | ||
|
|
6c47de0170 | ||
|
|
8793196bb3 | ||
|
|
a3a9a8e3f1 | ||
|
|
bef5b48fce | ||
|
|
bc0ba2f524 | ||
|
|
1b387dabde | ||
|
|
fe8cb7c461 | ||
|
|
bfbf62d398 | ||
|
|
b22b845d57 | ||
|
|
104a62e24d | ||
|
|
4639911a04 | ||
|
|
6677f2f5d4 | ||
|
|
8adb16e1f6 | ||
|
|
9c9e93974e | ||
|
|
44a6604fe8 | ||
|
|
47a18666b6 | ||
|
|
a231ebc408 | ||
|
|
33ab2f9cc5 | ||
|
|
e56c1a5853 | ||
|
|
27a47d4e4a | ||
|
|
614e5e62af | ||
|
|
f45a2e7806 | ||
|
|
c03485b93e | ||
|
|
900e668cd6 | ||
|
|
2657e1194c | ||
|
|
ec5ad089a3 | ||
|
|
69a3354617 | ||
|
|
6e60d30970 | ||
|
|
d6fa1f9cbc | ||
|
|
bc8dccd4b5 | ||
|
|
14f48ec440 | ||
|
|
fd1b847077 | ||
|
|
ed3c0e42fb | ||
|
|
d72d6d925e | ||
|
|
4ae034b21c | ||
|
|
bbc7a1fff0 | ||
|
|
68ed3e4996 | ||
|
|
03ae6366ea | ||
|
|
af2f469b84 | ||
|
|
a64699d064 | ||
|
|
ac96baae66 | ||
|
|
15d9569fa4 | ||
|
|
bd99affb13 | ||
|
|
88166b7c73 | ||
|
|
3543ebb9a6 | ||
|
|
924f239d1b | ||
|
|
b641285cf4 | ||
|
|
c22ce3b9a2 | ||
|
|
64091b5463 | ||
|
|
09f0b251ab | ||
|
|
9bf22e5e13 | ||
|
|
360e1e327e | ||
|
|
4b8bc65fb7 | ||
|
|
1b9d91936b | ||
|
|
7457432c2a | ||
|
|
30bcc8e7f0 | ||
|
|
6232bf070d | ||
|
|
978b0ed811 | ||
|
|
24acd14da0 | ||
|
|
4950b69152 | ||
|
|
f25da27c58 | ||
|
|
12a5c4a311 | ||
|
|
3fcc163261 | ||
|
|
18a670ae29 | ||
|
|
f443fef091 | ||
|
|
58adf75c18 | ||
|
|
bee04bec44 | ||
|
|
01cc32004a | ||
|
|
5ede0d35f2 | ||
|
|
a1b8d951c1 | ||
|
|
880e2401e1 | ||
|
|
3434bd8460 | ||
|
|
239db35ba0 | ||
|
|
6310750168 | ||
|
|
133e41e3be | ||
|
|
b616cfa75c | ||
|
|
86a0b5f59a | ||
|
|
becf029583 | ||
|
|
f36f2357ef | ||
|
|
faa6d91f7c | ||
|
|
be5ecc6d0d | ||
|
|
00a18d54bb | ||
|
|
bad20c3e0b | ||
|
|
14a72dec15 | ||
|
|
7ef43caa1e | ||
|
|
244c4c6201 | ||
|
|
8d29947e32 | ||
|
|
29fc705672 | ||
|
|
2859db15fe | ||
|
|
9ab020518e | ||
|
|
838635ae4d | ||
|
|
a88e4932e6 | ||
|
|
56c94a2986 | ||
|
|
a4c3d9cb17 | ||
|
|
c31d392e19 | ||
|
|
a34a5c4db0 | ||
|
|
0441b9fb50 | ||
|
|
3e871ea33d | ||
|
|
54dda91726 | ||
|
|
0a19570f2c | ||
|
|
f280aa227e | ||
|
|
af34dc4d4d | ||
|
|
0ab1079c9c | ||
|
|
d2cb0bde91 | ||
|
|
5b34f7cf8c | ||
|
|
9e6e34eda0 | ||
|
|
cfd6cdc50f | ||
|
|
78346cda46 | ||
|
|
c547ab4570 | ||
|
|
939b54787e | ||
|
|
7b5b81504b | ||
|
|
5578a274f6 | ||
|
|
9e0c4a89f3 | ||
|
|
426728058c | ||
|
|
18390503b5 | ||
|
|
6e79b8404a | ||
|
|
4567272baa | ||
|
|
6ff3a37665 | ||
|
|
5420314784 | ||
|
|
f1dad4c9fb | ||
|
|
aba0b29c77 | ||
|
|
638263e8eb | ||
|
|
e2040b7194 | ||
|
|
0006e3b4bd | ||
|
|
06efd01032 | ||
|
|
1a20bd2f4d | ||
|
|
598cf61eb4 | ||
|
|
7b6772e77b | ||
|
|
c4bfa6d4d8 | ||
|
|
700ebc53f8 | ||
|
|
4db83293e5 | ||
|
|
0fcdc2e118 | ||
|
|
4b8d44aa2e | ||
|
|
915e716936 | ||
|
|
bb63232f55 | ||
|
|
43288b2e97 | ||
|
|
824eade8b2 | ||
|
|
df26058172 | ||
|
|
2f3219704e | ||
|
|
5c0532e6c6 | ||
|
|
a4d5b74b57 | ||
|
|
864106d336 | ||
|
|
5a612e792e | ||
|
|
e473dfc15e | ||
|
|
f931316dc8 | ||
|
|
e323a315e1 | ||
|
|
a55a2bcca0 | ||
|
|
f0c739c94c | ||
|
|
60db5abb54 | ||
|
|
9ab7356730 | ||
|
|
7f2537f9b1 | ||
|
|
6fe3ca1058 | ||
|
|
99dbb3abed | ||
|
|
053bdd0467 | ||
|
|
5554dce924 | ||
|
|
ec7a4734df | ||
|
|
40e3e71b48 | ||
|
|
5eed80c28e | ||
|
|
e2436ad796 | ||
|
|
7f0d82e960 | ||
|
|
5ecdca28fb | ||
|
|
67bd6eac99 | ||
|
|
f8ce8ece1e | ||
|
|
679521c8a0 | ||
|
|
f8c1644dee | ||
|
|
882e9731ac | ||
|
|
3cd882f618 | ||
|
|
98e333cef9 | ||
|
|
21a0063756 | ||
|
|
76f1a82746 | ||
|
|
e38dd346d9 | ||
|
|
a8184ec17d | ||
|
|
5fb751222b | ||
|
|
9910af04b0 | ||
|
|
6f5c86775b | ||
|
|
9c78af65e1 | ||
|
|
e14010da35 | ||
|
|
c61278f1ad | ||
|
|
576c668d84 | ||
|
|
f93a464b7d | ||
|
|
06271678a6 | ||
|
|
af0ea4d555 | ||
|
|
e448e87252 | ||
|
|
e4c54cc655 | ||
|
|
671338425a | ||
|
|
5237cf9eb1 | ||
|
|
33586f4bdf | ||
|
|
2cc05e1878 | ||
|
|
44c0f409a9 | ||
|
|
dde6d8e623 | ||
|
|
f387e28ed4 | ||
|
|
e0072630f3 | ||
|
|
fdf80c4584 | ||
|
|
68b3f1a8e6 | ||
|
|
f044f3ece2 | ||
|
|
46312cb44c | ||
|
|
167a548112 | ||
|
|
a381c91af7 | ||
|
|
eb0446bfe1 | ||
|
|
62fcf8402c | ||
|
|
f320f6e9b6 | ||
|
|
2c387f6ae6 | ||
|
|
702145dada | ||
|
|
a1973faa06 | ||
|
|
ac7fc587ee | ||
|
|
240487c258 | ||
|
|
4e07c7ef4b | ||
|
|
147791dbcd | ||
|
|
caf7056ce0 | ||
|
|
38e42cf71e | ||
|
|
584a12e1f5 | ||
|
|
d601919dc4 | ||
|
|
e5351c573b | ||
|
|
ccff5c5921 | ||
|
|
c3ef992219 | ||
|
|
c698d27a29 | ||
|
|
05162ebd59 | ||
|
|
6f991b3238 | ||
|
|
a14373a3e6 | ||
|
|
6a61dc47ac | ||
|
|
971729dfdd | ||
|
|
5c1feb2848 | ||
|
|
4455bf13c9 | ||
|
|
f28b0316f4 | ||
|
|
9999b3aa0c | ||
|
|
f9734dbc8b | ||
|
|
c1bd469086 | ||
|
|
900ba886ed | ||
|
|
ab0dce5dea | ||
|
|
6327670b6f | ||
|
|
7717b295bd | ||
|
|
b243d25399 | ||
|
|
59b339aba5 | ||
|
|
0d6ada13c4 | ||
|
|
dd32e61fcc | ||
|
|
cbf533aa7d | ||
|
|
5bccb1a555 | ||
|
|
139a364da6 | ||
|
|
60fcafa3b8 | ||
|
|
d7ef4adbc8 | ||
|
|
c89e5785d8 | ||
|
|
af910aa3f7 | ||
|
|
7e873880f5 | ||
|
|
1be0edaf03 | ||
|
|
609e498973 | ||
|
|
1585b7a142 | ||
|
|
c55ac659c1 | ||
|
|
1de52f7b64 | ||
|
|
26a6eb506e | ||
|
|
ede3e669c7 | ||
|
|
d00aa21c96 | ||
|
|
6181098f68 | ||
|
|
1d4c1624c4 | ||
|
|
899d05bc32 | ||
|
|
15856574d7 | ||
|
|
c09f8e97f7 | ||
|
|
4fb7f099de | ||
|
|
90c6283742 | ||
|
|
872d8584fb | ||
|
|
74afe433fb | ||
|
|
e85d6a39f8 | ||
|
|
2a41e55ff2 | ||
|
|
1e30811112 | ||
|
|
22f0d752ea | ||
|
|
4675bae804 | ||
|
|
57bd3c5a4e | ||
|
|
29db2dcd14 | ||
|
|
df153ee1a1 | ||
|
|
331c12269c | ||
|
|
d7844a1e39 | ||
|
|
d96b82500a | ||
|
|
74f1da81f2 | ||
|
|
472bc529f9 | ||
|
|
4266c0b279 |
15
.editorconfig
Normal file
15
.editorconfig
Normal file
@@ -0,0 +1,15 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
max_line_length = 250
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{js,json}]
|
||||
indent_size = 4
|
||||
indent_style = tab
|
||||
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
||||
modules/default/calendar/vendor/*
|
||||
31
.eslintrc.json
Normal file
31
.eslintrc.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"extends": ["eslint:recommended", "plugin:prettier/recommended", "plugin:jsdoc/recommended"],
|
||||
"plugins": ["prettier", "jsdoc", "jest"],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"jest/globals": true,
|
||||
"node": true
|
||||
},
|
||||
"globals": {
|
||||
"config": true,
|
||||
"Log": true,
|
||||
"MM": true,
|
||||
"Module": true,
|
||||
"moment": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2017,
|
||||
"ecmaFeatures": {
|
||||
"globalReturn": true
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"eqeqeq": "error",
|
||||
"no-prototype-builtins": "off",
|
||||
"no-unused-vars": "off",
|
||||
"no-useless-return": "error"
|
||||
}
|
||||
}
|
||||
49
.github/CONTRIBUTING.md
vendored
Normal file
49
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# Contribution Policy for MagicMirror²
|
||||
|
||||
Thanks for contributing to MagicMirror²!
|
||||
|
||||
We hold our code to standard, and these standards are documented below.
|
||||
|
||||
If you wish to run our linters, use `npm run lint` without any arguments.
|
||||
|
||||
### JavaScript: Run ESLint
|
||||
|
||||
We use [ESLint](https://eslint.org) on our JavaScript files.
|
||||
|
||||
Our ESLint configuration is in our .eslintrc.json and .eslintignore files.
|
||||
|
||||
To run ESLint, use `npm run lint:js`.
|
||||
|
||||
### CSS: Run StyleLint
|
||||
|
||||
We use [StyleLint](https://stylelint.io) to lint our CSS. Our configuration is in our .stylelintrc file.
|
||||
|
||||
To run StyleLint, use `npm run lint:css`.
|
||||
|
||||
### Submitting Issues
|
||||
|
||||
Please only submit reproducible issues.
|
||||
|
||||
If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt)
|
||||
|
||||
Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting)
|
||||
|
||||
When submitting a new issue, please supply the following information:
|
||||
|
||||
**Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3/4, Windows, Mac, Linux, System V UNIX).
|
||||
|
||||
**Node Version**: Make sure it's version 12 or later (recommended is 14).
|
||||
|
||||
**MagicMirror Version**: Please let us know which version of MagicMirror you are running. It can be found in the `package.json` file.
|
||||
|
||||
**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem.
|
||||
|
||||
**Steps to Reproduce**: List the step by step process to reproduce the issue.
|
||||
|
||||
**Expected Results**: Describe what you expected to see.
|
||||
|
||||
**Actual Results**: Describe what you actually saw.
|
||||
|
||||
**Configuration**: What does the used config.js file look like? Don't forget to remove any sensitive information!
|
||||
|
||||
**Additional Notes**: Provide any other relevant notes not previously mentioned. This is optional.
|
||||
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
github: MichMich
|
||||
custom: ["https://magicmirror.builders/#donate"]
|
||||
50
.github/ISSUE_TEMPLATE.md
vendored
Normal file
50
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
Hello and thank you for opening an issue.
|
||||
|
||||
**Please make sure that you have read the following lines before submitting your Issue:**
|
||||
|
||||
## I'm not sure if this is a bug
|
||||
|
||||
If you're not sure if it's a real bug or if it's just you, please open a topic on the forum: [https://forum.magicmirror.builders/category/15/bug-hunt](https://forum.magicmirror.builders/category/15/bug-hunt)
|
||||
|
||||
## I'm having troubles installing or configuring MagicMirror
|
||||
|
||||
Problems installing or configuring your MagicMirror? Check out: [https://forum.magicmirror.builders/category/10/troubleshooting](https://forum.magicmirror.builders/category/10/troubleshooting)
|
||||
|
||||
A common problem is that your config file could be invalid. Please run in your MagicMirror directory: `npm run config:check` and see if it reports an error.
|
||||
|
||||
## I found a bug in the MagicMirror installer
|
||||
|
||||
If you are facing an issue or found a bug while trying to install MagicMirror via the installer please report it in the respective GitHub repository:
|
||||
[https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts)
|
||||
|
||||
## I found a bug in the MagicMirror Docker image
|
||||
|
||||
If you are facing an issue or found a bug while running MagicMirror inside a Docker container please create an issue in the corresponding repository:
|
||||
|
||||
- karsten13/magicmirror: [https://gitlab.com/khassel/magicmirror](https://gitlab.com/khassel/magicmirror)
|
||||
- (deprecated) bastilimbach/docker-magicmirror: [https://github.com/bastilimbach/docker-MagicMirror](https://github.com/bastilimbach/docker-MagicMirror)
|
||||
|
||||
---
|
||||
|
||||
## I found a bug in MagicMirror
|
||||
|
||||
Please make sure to only submit reproducible issues. You can safely remove everything above the dividing line.
|
||||
When submitting a new issue, please supply the following information:
|
||||
|
||||
**Platform**: Place your platform here... give us your web browser/Electron version _and_ your hardware (Raspberry Pi 2/3/4, Windows, Mac, Linux, System V UNIX).
|
||||
|
||||
**Node Version**: Make sure it's version 12 or later (recommended is 14).
|
||||
|
||||
**MagicMirror Version**: Please let us know which version of MagicMirror you are running. It can be found in the `package.json` file.
|
||||
|
||||
**Description**: Provide a detailed description about the issue and include specific details to help us understand the problem. Adding screenshots will help describing the problem.
|
||||
|
||||
**Steps to Reproduce**: List the step by step process to reproduce the issue.
|
||||
|
||||
**Expected Results**: Describe what you expected to see.
|
||||
|
||||
**Actual Results**: Describe what you actually saw.
|
||||
|
||||
**Configuration**: What does the used config.js file look like? Don't forget to remove any sensitive information!
|
||||
|
||||
**Additional Notes**: Provide any other relevant notes not previously mentioned. This is optional.
|
||||
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
25
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
Hello and thank you for wanting to contribute to the MagicMirror project
|
||||
|
||||
**Please make sure that you have followed these 4 rules before submitting your Pull Request:**
|
||||
|
||||
> 1. Base your pull requests against the `develop` branch.
|
||||
>
|
||||
> 2. Include these infos in the description:
|
||||
>
|
||||
> - Does the pull request solve a **related** issue?
|
||||
> - If so, can you reference the issue like this `Fixes #<issue_number>`?
|
||||
> - What does the pull request accomplish? Use a list if needed.
|
||||
> - If it includes major visual changes please add screenshots.
|
||||
>
|
||||
> 3. Please run `npm run lint:prettier` before submitting so that
|
||||
> style issues are fixed.
|
||||
>
|
||||
> 4. Don't forget to add an entry about your changes to
|
||||
> the CHANGELOG.md file.
|
||||
|
||||
**Note**: Sometimes the development moves very fast. It is highly
|
||||
recommended that you update your branch of `develop` before creating a
|
||||
pull request to send us your changes. This makes everyone's lives
|
||||
easier (including yours) and helps us out on the development team.
|
||||
|
||||
Thanks again and have a nice day!
|
||||
6
.github/codecov.yml
vendored
Normal file
6
.github/codecov.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
# advanced settings
|
||||
informational: true
|
||||
BIN
.github/header.png
vendored
Normal file
BIN
.github/header.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
19
.github/stale.yml
vendored
Normal file
19
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- under investigation
|
||||
- pr welcome
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
37
.github/workflows/automated-tests.yml
vendored
Normal file
37
.github/workflows/automated-tests.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: "Run Automated Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, develop]
|
||||
pull_request:
|
||||
branches: [master, develop]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x, 16.x]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install dependencies and run tests
|
||||
run: |
|
||||
Xvfb :99 -screen 0 1024x768x16 &
|
||||
export DISPLAY=:99
|
||||
npm install
|
||||
touch css/custom.css
|
||||
npm run test:prettier
|
||||
npm run test:js
|
||||
npm run test:css
|
||||
npm run test:unit
|
||||
npm run test:e2e
|
||||
npm run test:electron
|
||||
29
.github/workflows/codecov-test-suites.yml
vendored
Normal file
29
.github/workflows/codecov-test-suites.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# This workflow runs the automated test and uploads the coverage results to codecov.io
|
||||
|
||||
name: "Run Codecov Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, develop]
|
||||
pull_request:
|
||||
branches: [master, develop]
|
||||
|
||||
jobs:
|
||||
run-and-upload-coverage-report:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Install dependencies and run coverage
|
||||
run: |
|
||||
Xvfb :99 -screen 0 1024x768x16 &
|
||||
export DISPLAY=:99
|
||||
npm ci
|
||||
touch css/custom.css
|
||||
npm run test:coverage
|
||||
- name: Upload coverage results to codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
file: ./coverage/lcov.info
|
||||
fail_ci_if_error: true
|
||||
20
.github/workflows/enforce-changelog.yml
vendored
Normal file
20
.github/workflows/enforce-changelog.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# This workflow enforces the update of a changelog file on every pull request
|
||||
|
||||
name: "Enforce Changelog"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Enforce changelog️
|
||||
uses: dangoslen/changelog-enforcer@v1.6.1
|
||||
with:
|
||||
changeLogPath: "CHANGELOG.md"
|
||||
skipLabels: "Skip Changelog"
|
||||
82
.gitignore
vendored
Normal file
82
.gitignore
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
# Various Node ignoramuses.
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
lib-cov
|
||||
coverage
|
||||
.lock-wscript
|
||||
build/Release
|
||||
/node_modules/**/*
|
||||
fonts/node_modules/**/*
|
||||
vendor/node_modules/**/*
|
||||
!/tests/node_modules/**/*
|
||||
jspm_modules
|
||||
.npm
|
||||
.node_repl_history
|
||||
.nyc_output/
|
||||
|
||||
# Visual Studio Code ignoramuses.
|
||||
.vscode/
|
||||
|
||||
# IDE Code ignoramuses.
|
||||
.idea/
|
||||
|
||||
# Various Windows ignoramuses.
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
||||
|
||||
# Various OSX ignoramuses.
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
._*
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Various Linux ignoramuses.
|
||||
.fuse_hidden*
|
||||
.directory
|
||||
.Trash-*
|
||||
|
||||
# Ignore all modules except the default modules.
|
||||
/modules/**
|
||||
!/modules/default
|
||||
!/modules/default/**
|
||||
!/modules/README.md**
|
||||
|
||||
# Ignore changes to the custom css files.
|
||||
/css/custom.css
|
||||
|
||||
# Ignore users config file but keep the sample.
|
||||
/config/*
|
||||
!/config/config.js.sample
|
||||
|
||||
# Vim
|
||||
## swap
|
||||
[._]*.s[a-w][a-z]
|
||||
[._]s[a-w][a-z]
|
||||
|
||||
## diff patch
|
||||
*.orig
|
||||
*.rej
|
||||
*.bak
|
||||
4
.husky/pre-commit
Executable file
4
.husky/pre-commit
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm run lint:staged
|
||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@@ -0,0 +1,4 @@
|
||||
/config
|
||||
/coverage
|
||||
.nyc_output
|
||||
package-lock.json
|
||||
3
.prettierrc.json
Normal file
3
.prettierrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"trailingComma": "none"
|
||||
}
|
||||
7
.stylelintrc.json
Normal file
7
.stylelintrc.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": ["stylelint-prettier/recommended"],
|
||||
"plugins": ["stylelint-prettier"],
|
||||
"rules": {
|
||||
"prettier/prettier": true
|
||||
}
|
||||
}
|
||||
1070
CHANGELOG.md
Normal file
1070
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
17
LICENSE.md
Normal file
17
LICENSE.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# The MIT License (MIT)
|
||||
|
||||
Copyright © 2016-2021 Michael Teeuw
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the “Software”), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
**The software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software.**
|
||||
71
README.md
71
README.md
@@ -1,52 +1,51 @@
|
||||
MagicMirror
|
||||
===========
|
||||

|
||||
|
||||
##Introduction
|
||||
<p style="text-align: center">
|
||||
<a href="https://david-dm.org/MichMich/MagicMirror"><img src="https://david-dm.org/MichMich/MagicMirror.svg" alt="Dependency Status"></a>
|
||||
<a href="https://david-dm.org/MichMich/MagicMirror?type=dev"><img src="https://david-dm.org/MichMich/MagicMirror/dev-status.svg" alt="devDependency Status"></a>
|
||||
<a href="https://bestpractices.coreinfrastructure.org/projects/347"><img src="https://bestpractices.coreinfrastructure.org/projects/347/badge" alt="CLI Best Practices"></a>
|
||||
<a href="https://codecov.io/gh/MichMich/MagicMirror"><img src="https://codecov.io/gh/MichMich/MagicMirror/branch/master/graph/badge.svg?token=LEG1KitZR6" alt="CodeCov Status"/></a>
|
||||
<a href="https://choosealicense.com/licenses/mit"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
|
||||
<a href="https://github.com/MichMich/MagicMirror/actions?query=workflow%3A%22Automated+Tests%22"><img src="https://github.com/MichMich/MagicMirror/workflows/Automated%20Tests/badge.svg" alt="Tests"></a>
|
||||
</p>
|
||||
|
||||
The super magic interface of my personal Magic Mirror. More information about this project can be found on my [blog](http://michaelteeuw.nl/tagged/magicmirror).
|
||||
**MagicMirror²** is an open source modular smart mirror platform. With a growing list of installable modules, the **MagicMirror²** allows you to convert your hallway or bathroom mirror into your personal assistant. **MagicMirror²** is built by the creator of [the original MagicMirror](https://michaelteeuw.nl/tagged/magicmirror) with the incredible help of a [growing community of contributors](https://github.com/MichMich/MagicMirror/graphs/contributors).
|
||||
|
||||
Runs as a php script on a web server with basically no external dependencies. *Can use socket.io for XBEE integration, but isn't required for basic functionality*.
|
||||
MagicMirror² focuses on a modular plugin system and uses [Electron](https://www.electronjs.org/) as an application wrapper. So no more web server or browser installs necessary!
|
||||
|
||||
## Documentation
|
||||
|
||||
##Configuration
|
||||
For the full documentation including **[installation instructions](https://docs.magicmirror.builders/getting-started/installation.html)**, please visit our dedicated documentation website: [https://docs.magicmirror.builders](https://docs.magicmirror.builders).
|
||||
|
||||
Modify `js/config.js` to change some general variables (language, weather location, compliments, news feed RSS and to add your own ICS calendar)
|
||||
## Links
|
||||
|
||||
To use the OpenWeatherMap API, you'll need a free API key. Checkout [this blogpost](http://michaelteeuw.nl/post/131504229357/what-happened-to-the-weather) for more information.
|
||||
- Website: [https://magicmirror.builders](https://magicmirror.builders)
|
||||
- Documentation: [https://docs.magicmirror.builders](https://docs.magicmirror.builders)
|
||||
- Forum: [https://forum.magicmirror.builders](https://forum.magicmirror.builders)
|
||||
- Technical discussions: https://forum.magicmirror.builders/category/11/core-system
|
||||
- Discord: [https://discord.gg/J5BAtvx](https://discord.gg/J5BAtvx)
|
||||
- Blog: [https://michaelteeuw.nl/tagged/magicmirror](https://michaelteeuw.nl/tagged/magicmirror)
|
||||
- Donations: [https://magicmirror.builders/#donate](https://magicmirror.builders/#donate)
|
||||
|
||||
##Code
|
||||
## Contributing Guidelines
|
||||
|
||||
###[main.js](js/main.js)
|
||||
Contributions of all kinds are welcome, not only in the form of code but also with regards to
|
||||
|
||||
This file initiates the separate pieces of functionality that will appear in the view. It also includes various utility functions that are used to update what is visible.
|
||||
- bug reports
|
||||
- documentation
|
||||
- translations
|
||||
|
||||
###[Calendar](js/calendar)
|
||||
For the full contribution guidelines, check out: [https://docs.magicmirror.builders/getting-started/contributing.html](https://docs.magicmirror.builders/getting-started/contributing.html)
|
||||
|
||||
Parsing functionality for the calendar that retrieves and updates the calendar based on the interval set at the top of the [calendar.js](js/calendar/calendar.js) file. This was actually a straight pull from the original main.js file but the parsing code may deserve an upgrade.
|
||||
## Enjoying MagicMirror? Consider a donation!
|
||||
|
||||
###[Compliments](js/compliments)
|
||||
MagicMirror² is opensource and free. That doesn't mean we don't need any money.
|
||||
|
||||
Functionality related to inserting compliments into the view and rotating them based on a specific interval set at the top of the [compliments.js](js/compliments/compliments.js) file.
|
||||
Please consider a donation to help us cover the ongoing costs like webservers and email services.
|
||||
If we receive enough donations we might even be able to free up some working hours and spend some extra time improving the MagicMirror² core.
|
||||
|
||||
###[News](js/news)
|
||||
To donate, please follow [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) link.
|
||||
|
||||
Takes an array of news feeds (or a single string) from the config file and retrieves each one so that it can be displayed in a loop based on the interval set at the top of the [news.js](js/news/news.js) file.
|
||||
|
||||
###[Time](js/time)
|
||||
|
||||
Updates the time on the screen on one second interval.
|
||||
|
||||
###[Version](js/version)
|
||||
|
||||
Checks the git version and refreshes if a new version has been pulled.
|
||||
|
||||
###[Weather](js/weather)
|
||||
|
||||
Takes the user's inserted location, language, unit type, and OpenWeatherMap API key and grabs the five day weather forecast from OpenWeatherMap. You need to set the API key in the config for this to work. (See *configuration*.)
|
||||
|
||||
##Extensions
|
||||
|
||||
###[MagicMirror-Extensions by PaViRo](https://github.com/paviro/MagicMirror-Extensions)
|
||||
|
||||
**Current features:** FRITZ!Box Callmonitor <br>
|
||||
**Future features:** Faceregognition, personalized views, online banking through HBCI and multiple calenders based on faceregognition.
|
||||
<p style="text-align: center">
|
||||
<a href="https://forum.magicmirror.builders/topic/728/magicmirror-is-voted-number-1-in-the-magpi-top-50"><img src="https://magicmirror.builders/img/magpi-best-watermark-custom.png" width="150" alt="MagPi Top 50"></a>
|
||||
</p>
|
||||
|
||||
126
clientonly/index.js
Normal file
126
clientonly/index.js
Normal file
@@ -0,0 +1,126 @@
|
||||
"use strict";
|
||||
|
||||
// Use separate scope to prevent global scope pollution
|
||||
(function () {
|
||||
const config = {};
|
||||
|
||||
/**
|
||||
* Helper function to get server address/hostname from either the commandline or env
|
||||
*/
|
||||
function getServerAddress() {
|
||||
/**
|
||||
* Get command line parameters
|
||||
* Assumes that a cmdline parameter is defined with `--key [value]`
|
||||
*
|
||||
* @param {string} key key to look for at the command line
|
||||
* @param {string} defaultValue value if no key is given at the command line
|
||||
* @returns {string} the value of the parameter
|
||||
*/
|
||||
function getCommandLineParameter(key, defaultValue = undefined) {
|
||||
const index = process.argv.indexOf(`--${key}`);
|
||||
const value = index > -1 ? process.argv[index + 1] : undefined;
|
||||
return value !== undefined ? String(value) : defaultValue;
|
||||
}
|
||||
|
||||
// Prefer command line arguments over environment variables
|
||||
["address", "port"].forEach((key) => {
|
||||
config[key] = getCommandLineParameter(key, process.env[key.toUpperCase()]);
|
||||
});
|
||||
|
||||
// determine if "--use-tls"-flag was provided
|
||||
config["tls"] = process.argv.indexOf("--use-tls") > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the config from the specified server url
|
||||
*
|
||||
* @param {string} url location where the server is running.
|
||||
* @returns {Promise} the config
|
||||
*/
|
||||
function getServerConfig(url) {
|
||||
// Return new pending promise
|
||||
return new Promise((resolve, reject) => {
|
||||
// Select http or https module, depending on requested url
|
||||
const lib = url.startsWith("https") ? require("https") : require("http");
|
||||
const request = lib.get(url, (response) => {
|
||||
let configData = "";
|
||||
|
||||
// Gather incoming data
|
||||
response.on("data", function (chunk) {
|
||||
configData += chunk;
|
||||
});
|
||||
// Resolve promise at the end of the HTTP/HTTPS stream
|
||||
response.on("end", function () {
|
||||
resolve(JSON.parse(configData));
|
||||
});
|
||||
});
|
||||
|
||||
request.on("error", function (error) {
|
||||
reject(new Error(`Unable to read config from server (${url} (${error.message}`));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a message to the console in case of errors
|
||||
*
|
||||
* @param {string} message error message to print
|
||||
* @param {number} code error code for the exit call
|
||||
*/
|
||||
function fail(message, code = 1) {
|
||||
if (message !== undefined && typeof message === "string") {
|
||||
console.log(message);
|
||||
} else {
|
||||
console.log("Usage: 'node clientonly --address 192.168.1.10 --port 8080 [--use-tls]'");
|
||||
}
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
getServerAddress();
|
||||
|
||||
(config.address && config.port) || fail();
|
||||
const prefix = config.tls ? "https://" : "http://";
|
||||
|
||||
// Only start the client if a non-local server was provided
|
||||
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].indexOf(config.address) === -1) {
|
||||
getServerConfig(`${prefix}${config.address}:${config.port}/config/`)
|
||||
.then(function (configReturn) {
|
||||
// Pass along the server config via an environment variable
|
||||
const env = Object.create(process.env);
|
||||
const options = { env: env };
|
||||
configReturn.address = config.address;
|
||||
configReturn.port = config.port;
|
||||
configReturn.tls = config.tls;
|
||||
env.config = JSON.stringify(configReturn);
|
||||
|
||||
// Spawn electron application
|
||||
const electron = require("electron");
|
||||
const child = require("child_process").spawn(electron, ["js/electron.js"], options);
|
||||
|
||||
// Pipe all child process output to current stdout
|
||||
child.stdout.on("data", function (buf) {
|
||||
process.stdout.write(`Client: ${buf}`);
|
||||
});
|
||||
|
||||
// Pipe all child process errors to current stderr
|
||||
child.stderr.on("data", function (buf) {
|
||||
process.stderr.write(`Client: ${buf}`);
|
||||
});
|
||||
|
||||
child.on("error", function (err) {
|
||||
process.stdout.write(`Client: ${err}`);
|
||||
});
|
||||
|
||||
child.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
console.log(`There something wrong. The clientonly is not running code ${code}`);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(function (reason) {
|
||||
fail(`Unable to connect to server: (${reason})`);
|
||||
});
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
})();
|
||||
112
config/config.js.sample
Normal file
112
config/config.js.sample
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Magic Mirror Config Sample
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*
|
||||
* For more information on how you can configure this file
|
||||
* see https://docs.magicmirror.builders/getting-started/configuration.html#general
|
||||
* and https://docs.magicmirror.builders/modules/configuration.html
|
||||
*/
|
||||
let config = {
|
||||
address: "localhost", // Address to listen on, can be:
|
||||
// - "localhost", "127.0.0.1", "::1" to listen on loopback interface
|
||||
// - another specific IPv4/6 to listen on a specific interface
|
||||
// - "0.0.0.0", "::" to listen on any interface
|
||||
// Default, when address config is left out or empty, is "localhost"
|
||||
port: 8080,
|
||||
basePath: "/", // The URL path where MagicMirror is hosted. If you are using a Reverse proxy
|
||||
// you must set the sub path here. basePath must end with a /
|
||||
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], // Set [] to allow all IP addresses
|
||||
// or add a specific IPv4 of 192.168.1.5 :
|
||||
// ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"],
|
||||
// or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format :
|
||||
// ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"],
|
||||
|
||||
useHttps: false, // Support HTTPS or not, default "false" will use HTTP
|
||||
httpsPrivateKey: "", // HTTPS private key path, only require when useHttps is true
|
||||
httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true
|
||||
|
||||
language: "en",
|
||||
locale: "en-US",
|
||||
logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging
|
||||
timeFormat: 24,
|
||||
units: "metric",
|
||||
// serverOnly: true/false/"local" ,
|
||||
// local for armv6l processors, default
|
||||
// starts serveronly and then starts chrome browser
|
||||
// false, default for all NON-armv6l devices
|
||||
// true, force serveronly mode, because you want to.. no UI on this device
|
||||
|
||||
modules: [
|
||||
{
|
||||
module: "alert",
|
||||
},
|
||||
{
|
||||
module: "updatenotification",
|
||||
position: "top_bar"
|
||||
},
|
||||
{
|
||||
module: "clock",
|
||||
position: "top_left"
|
||||
},
|
||||
{
|
||||
module: "calendar",
|
||||
header: "US Holidays",
|
||||
position: "top_left",
|
||||
config: {
|
||||
calendars: [
|
||||
{
|
||||
symbol: "calendar-check",
|
||||
url: "webcal://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "compliments",
|
||||
position: "lower_third"
|
||||
},
|
||||
{
|
||||
module: "weather",
|
||||
position: "top_right",
|
||||
config: {
|
||||
weatherProvider: "openweathermap",
|
||||
type: "current",
|
||||
location: "New York",
|
||||
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
||||
apiKey: "YOUR_OPENWEATHER_API_KEY"
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "weather",
|
||||
position: "top_right",
|
||||
header: "Weather Forecast",
|
||||
config: {
|
||||
weatherProvider: "openweathermap",
|
||||
type: "forecast",
|
||||
location: "New York",
|
||||
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
||||
apiKey: "YOUR_OPENWEATHER_API_KEY"
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "newsfeed",
|
||||
position: "bottom_bar",
|
||||
config: {
|
||||
feeds: [
|
||||
{
|
||||
title: "New York Times",
|
||||
url: "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml"
|
||||
}
|
||||
],
|
||||
showSourceTitle: true,
|
||||
showPublishDate: true,
|
||||
broadcastNewsFeeds: true,
|
||||
broadcastNewsUpdates: true
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {module.exports = config;}
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
include "functions/gzip.php";
|
||||
$url = $_GET["url"];
|
||||
echo get_url($url);
|
||||
?>
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* @function get_url
|
||||
* @purpose To fetch GZipped web content.
|
||||
* @author Michael Teeuw
|
||||
*/
|
||||
function get_url($url) {
|
||||
/*
|
||||
* @array
|
||||
* Prepare the options that we need for our GZip request.
|
||||
*/
|
||||
$opts = array(
|
||||
"http" => array(
|
||||
"method" => "GET",
|
||||
"header" => "Accept-Language: en-US,en;q=0.8rn" . "Accept-Encoding: gzip,deflate,sdchrn" . "Accept-Charset:UTF-8,*;q=0.5rn" . "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 FirePHP/0.4rn",
|
||||
"ignore_errors" => true
|
||||
),
|
||||
/*
|
||||
* @array
|
||||
* Put a Band-Aid over some SSL issues.
|
||||
*/
|
||||
"ssl" => array(
|
||||
"verify_peer" => false,
|
||||
"verify_peer_name" => false
|
||||
)
|
||||
);
|
||||
$context = stream_context_create($opts);
|
||||
$content = file_get_contents($url, false, $context);
|
||||
/*
|
||||
* @note If http response header mentions that content is gzipped, then uncompress it.
|
||||
*/
|
||||
foreach($http_response_header as $c => $h) {
|
||||
if(stristr($h, "content-encoding") and stristr($h, "gzip")) {
|
||||
/*
|
||||
* @note Now, let's begin the actual purpose of this function:
|
||||
*/
|
||||
$content = gzinflate(substr($content, 10, -8));
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
?>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php
|
||||
echo json_encode(
|
||||
array(
|
||||
"gitHash" => trim(`git rev-parse HEAD`)
|
||||
)
|
||||
);
|
||||
?>
|
||||
31
css/custom.css.sample
Normal file
31
css/custom.css.sample
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Magic Mirror Custom CSS Sample
|
||||
*
|
||||
* Change color and fonts here.
|
||||
*
|
||||
* Beware that properties cannot be unitless, so for example write '--gap-body: 0px;' instead of just '--gap-body: 0;'
|
||||
*
|
||||
* MIT Licensed.
|
||||
*/
|
||||
|
||||
/* Uncomment and adjust accordingly if you want to import another font from the google-fonts-api: */
|
||||
/* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100;300;400;700&display=swap'); */
|
||||
|
||||
:root {
|
||||
--color-text: #999;
|
||||
--color-text-dimmed: #666;
|
||||
--color-text-bright: #fff;
|
||||
--color-background: black;
|
||||
|
||||
--font-primary: "Roboto Condensed";
|
||||
--font-secondary: "Roboto";
|
||||
|
||||
--font-size: 20px;
|
||||
--font-size-small: 0.75rem;
|
||||
|
||||
--gap-body-top: 60px;
|
||||
--gap-body-right: 60px;
|
||||
--gap-body-bottom: 60px;
|
||||
--gap-body-left: 60px;
|
||||
|
||||
--gap-modules: 30px;
|
||||
}
|
||||
440
css/main.css
440
css/main.css
@@ -1,224 +1,240 @@
|
||||
body,
|
||||
:root {
|
||||
--color-text: #999;
|
||||
--color-text-dimmed: #666;
|
||||
--color-text-bright: #fff;
|
||||
--color-background: #000;
|
||||
|
||||
--font-primary: "Roboto Condensed";
|
||||
--font-secondary: "Roboto";
|
||||
|
||||
--font-size: 20px;
|
||||
--font-size-small: 0.75rem;
|
||||
|
||||
--gap-body-top: 60px;
|
||||
--gap-body-right: 60px;
|
||||
--gap-body-bottom: 60px;
|
||||
--gap-body-left: 60px;
|
||||
|
||||
--gap-modules: 30px;
|
||||
}
|
||||
|
||||
html {
|
||||
background: #000;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family: "HelveticaNeue-Light", sans-serif;
|
||||
letter-spacing: -2px;
|
||||
color: #fff;
|
||||
font-size: 75px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: geometricprecision;
|
||||
cursor: none;
|
||||
overflow: hidden;
|
||||
background: var(--color-background);
|
||||
user-select: none;
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.wi {
|
||||
line-height: 75px;
|
||||
}
|
||||
|
||||
.top {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
}
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
left: 50px;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.center-ver {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
height: 200px;
|
||||
margin-top: -100px;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.lower-third {
|
||||
position: absolute;
|
||||
top: 66.666%;
|
||||
height: 200px;
|
||||
margin-top: -100px;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.center-hor {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
left: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
.xxsmall,
|
||||
.xsmall,
|
||||
.small {
|
||||
font-family: "HelveticaNeue-Medium", sans-serif;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.xxsmall {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.xxsmall .wi {
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.xsmall {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.xsmall .wi {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.small .wi {
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.medium {
|
||||
font-size: 35px;
|
||||
letter-spacing: -1px;
|
||||
font-family: "HelveticaNeue-Light", sans-serif;
|
||||
}
|
||||
|
||||
.medium .wi {
|
||||
line-height: 35px;
|
||||
}
|
||||
|
||||
.xdimmed {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.dimmed {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.light {
|
||||
font-family: "HelveticaNeue-UltraLight", sans-serif;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
top: -10px;
|
||||
display: inline-block;
|
||||
font-size: 45px;
|
||||
padding-right: 5px;
|
||||
font-weight: 100;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.icon-small {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
font-size: 20px;
|
||||
padding-left: 10px;
|
||||
padding-right: -10px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
.time .sec {
|
||||
font-size: 25px;
|
||||
color: #666;
|
||||
padding-left: 5px;
|
||||
position: relative;
|
||||
top: -35px;
|
||||
}
|
||||
|
||||
.forecast-table {
|
||||
float: right;
|
||||
text-align: right;
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.forecast-table .day,
|
||||
.forecast-table .temp-min,
|
||||
.forecast-table .temp-max {
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.forecast-table .temp-max {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.forecast-table .day {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.calendar-table {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.calendar-table .days {
|
||||
padding-left: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dishwasher {
|
||||
background-color: white;
|
||||
color: black;
|
||||
margin: 0 200px;
|
||||
font-size: 60px;
|
||||
border-radius: 1000px;
|
||||
border-radius: 1200px;
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'HelveticaNeue-UltraLight';
|
||||
src: url('font/HelveticaNeue-UltraLight.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src: url('font/HelveticaNeue-UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('font/HelveticaNeue-UltraLight.woff') format('woff'), /* Modern Browsers */
|
||||
url('font/HelveticaNeue-UltraLight.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('font/HelveticaNeue-UltraLight.svg#9453ea8da727d260bcdbfa605bdbb5d2') format('svg');
|
||||
/* Legacy iOS */
|
||||
font-style: normal;
|
||||
body {
|
||||
margin: var(--gap-body-top) var(--gap-body-right) var(--gap-body-bottom) var(--gap-body-left);
|
||||
position: absolute;
|
||||
height: calc(100% - var(--gap-body-top) - var(--gap-body-bottom));
|
||||
width: calc(100% - var(--gap-body-right) - var(--gap-body-left));
|
||||
background: var(--color-background);
|
||||
color: var(--color-text);
|
||||
font-family: var(--font-primary), sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default styles.
|
||||
*/
|
||||
|
||||
.dimmed {
|
||||
color: var(--color-text-dimmed);
|
||||
}
|
||||
|
||||
.normal {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.bright {
|
||||
color: var(--color-text-bright);
|
||||
}
|
||||
|
||||
.xsmall {
|
||||
font-size: var(--font-size-small);
|
||||
line-height: 1.275;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 1rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.medium {
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.225;
|
||||
}
|
||||
|
||||
.large {
|
||||
font-size: 3.25rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.xlarge {
|
||||
font-size: 3.75rem;
|
||||
line-height: 1;
|
||||
letter-spacing: -3px;
|
||||
}
|
||||
|
||||
.thin {
|
||||
font-family: var(--font-secondary), sans-serif;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'HelveticaNeue-Medium';
|
||||
src: url('font/HelveticaNeue-Medium.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src: url('font/HelveticaNeue-Medium.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('font/HelveticaNeue-Medium.woff') format('woff'), /* Modern Browsers */
|
||||
url('font/HelveticaNeue-Medium.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('font/HelveticaNeue-Medium.svg#d7af0fd9278f330eed98b60dddea7bd6') format('svg');
|
||||
/* Legacy iOS */
|
||||
font-style: normal;
|
||||
.light {
|
||||
font-family: var(--font-primary), sans-serif;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.regular {
|
||||
font-family: var(--font-primary), sans-serif;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'HelveticaNeue-Light';
|
||||
src: url('font/HelveticaNeue-Light.eot');
|
||||
/* IE9 Compat Modes */
|
||||
src: url('font/HelveticaNeue-Light.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('font/HelveticaNeue-Light.woff') format('woff'), /* Modern Browsers */
|
||||
url('font/HelveticaNeue-Light.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('font/HelveticaNeue-Light.svg#7384ecabcada72f0e077cd45d8e1c705') format('svg');
|
||||
/* Legacy iOS */
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
}
|
||||
.bold {
|
||||
font-family: var(--font-primary), sans-serif;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
header {
|
||||
text-transform: uppercase;
|
||||
font-size: var(--font-size-small);
|
||||
font-family: var(--font-primary), Arial, Helvetica, sans-serif;
|
||||
font-weight: 400;
|
||||
border-bottom: 1px solid var(--color-text-dimmed);
|
||||
line-height: 15px;
|
||||
padding-bottom: 5px;
|
||||
margin-bottom: 10px;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
sup {
|
||||
font-size: 50%;
|
||||
line-height: 50%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Module styles.
|
||||
*/
|
||||
|
||||
.module {
|
||||
margin-bottom: var(--gap-modules);
|
||||
}
|
||||
|
||||
.region.bottom .module {
|
||||
margin-top: var(--gap-modules);
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.no-wrap {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.pre-line {
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Region Definitions.
|
||||
*/
|
||||
|
||||
.region {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.region.fullscreen {
|
||||
position: absolute;
|
||||
top: calc(-1 * var(--gap-body-top));
|
||||
left: calc(-1 * var(--gap-body-left));
|
||||
right: calc(-1 * var(--gap-body-right));
|
||||
bottom: calc(-1 * var(--gap-body-bottom));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.region.fullscreen * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.region.right {
|
||||
right: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.region.top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.region.top.center,
|
||||
.region.bottom.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.region.top.right,
|
||||
.region.top.left,
|
||||
.region.top.center {
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.region.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.region.bottom.right,
|
||||
.region.bottom.center,
|
||||
.region.bottom.left {
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
.region.bar {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.region.third,
|
||||
.region.middle.center {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.region.upper.third {
|
||||
top: 33%;
|
||||
}
|
||||
|
||||
.region.middle.center {
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
.region.lower.third {
|
||||
top: 66%;
|
||||
}
|
||||
|
||||
.region.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.region table {
|
||||
width: 100%;
|
||||
border-spacing: 0;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
@@ -1,327 +0,0 @@
|
||||
/*!
|
||||
* Weather Icons Beta 1
|
||||
* Weather themed icons for Bootstrap
|
||||
* ------------------------------------------------------------------------------
|
||||
* Maintained at http://erikflowers.github.io/weather-icons
|
||||
* http://twitter.com/Erik_UX
|
||||
*
|
||||
* License
|
||||
* ------------------------------------------------------------------------------
|
||||
* - Fpmt licensed under SIL OFL 1.1 -
|
||||
* http://scripts.sil.org/OFL
|
||||
* - CSS and LESS are licensed under MIT License -
|
||||
* http://opensource.org/licenses/mit-license.html
|
||||
* - Documentation licensed under CC BY 3.0 -
|
||||
* http://creativecommons.org/licenses/by/3.0/
|
||||
* - Inspired by and works great as a companion with Font Aweosme
|
||||
* "Font Awesome by Dave Gandy - http://fontawesome.io"
|
||||
*
|
||||
* Weather Icons Bootstrap Package Author - Erik Flowers - erik@helloerik.com
|
||||
* Weather Icons gives full credit for inspiration to Font Awesome and makes no
|
||||
* claim to invention, intellectual property, or ownership of methodology.
|
||||
*
|
||||
* Support Open Source!
|
||||
*
|
||||
* ------------------------------------------------------------------------------
|
||||
* Email: erik@helloerik.com
|
||||
* Twitter: http://twitter.com/Erik_UX
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'weather';
|
||||
src: url('../font/weathericons-regular-webfont.eot');
|
||||
src: url('../font/weathericons-regular-webfont.eot?#iefix') format('embedded-opentype'), url('../font/weathericons-regular-webfont.woff') format('woff'), url('../font/weathericons-regular-webfont.ttf') format('truetype'), url('../font/weathericons-regular-webfont.svg#weathericons-regular-webfontRg') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
[class^="wi-"],
|
||||
[class*=" wi-"] {
|
||||
font-family: weather;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
text-decoration: inherit;
|
||||
text-transform: none;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
*margin-right: .3em;
|
||||
}
|
||||
[class^="wi-"]:before,
|
||||
[class*=" wi-"]:before {
|
||||
text-decoration: inherit;
|
||||
display: inline-block;
|
||||
speak: none;
|
||||
}
|
||||
.wi-day-cloudy-gusts:before {
|
||||
content: "\f000";
|
||||
}
|
||||
.wi-day-cloudy-windy:before {
|
||||
content: "\f001";
|
||||
}
|
||||
.wi-day-cloudy:before {
|
||||
content: "\f002";
|
||||
}
|
||||
.wi-day-fog:before {
|
||||
content: "\f003";
|
||||
}
|
||||
.wi-day-hail:before {
|
||||
content: "\f004";
|
||||
}
|
||||
.wi-day-lightning:before {
|
||||
content: "\f005";
|
||||
}
|
||||
.wi-day-rain-mix:before {
|
||||
content: "\f006";
|
||||
}
|
||||
.wi-day-rain-wind:before {
|
||||
content: "\f007";
|
||||
}
|
||||
.wi-day-rain:before {
|
||||
content: "\f008";
|
||||
}
|
||||
.wi-day-showers:before {
|
||||
content: "\f009";
|
||||
}
|
||||
.wi-day-snow:before {
|
||||
content: "\f00a";
|
||||
}
|
||||
.wi-day-sprinkle:before {
|
||||
content: "\f00b";
|
||||
}
|
||||
.wi-day-sunny-overcast:before {
|
||||
content: "\f00c";
|
||||
}
|
||||
.wi-day-sunny:before {
|
||||
content: "\f00d";
|
||||
}
|
||||
.wi-day-storm-showers:before {
|
||||
content: "\f00e";
|
||||
}
|
||||
.wi-day-thunderstorm:before {
|
||||
content: "\f010";
|
||||
}
|
||||
.wi-cloudy-gusts:before {
|
||||
content: "\f011";
|
||||
}
|
||||
.wi-cloudy-windy:before {
|
||||
content: "\f012";
|
||||
}
|
||||
.wi-cloudy:before {
|
||||
content: "\f013";
|
||||
}
|
||||
.wi-fog:before {
|
||||
content: "\f014";
|
||||
}
|
||||
.wi-hail:before {
|
||||
content: "\f015";
|
||||
}
|
||||
.wi-lightning:before {
|
||||
content: "\f016";
|
||||
}
|
||||
.wi-rain-mix:before {
|
||||
content: "\f017";
|
||||
}
|
||||
.wi-rain-wind:before {
|
||||
content: "\f018";
|
||||
}
|
||||
.wi-rain:before {
|
||||
content: "\f019";
|
||||
}
|
||||
.wi-showers:before {
|
||||
content: "\f01a";
|
||||
}
|
||||
.wi-snow:before {
|
||||
content: "\f01b";
|
||||
}
|
||||
.wi-sprinkle:before {
|
||||
content: "\f01c";
|
||||
}
|
||||
.wi-storm-showers:before {
|
||||
content: "\f01d";
|
||||
}
|
||||
.wi-thunderstorm:before {
|
||||
content: "\f01e";
|
||||
}
|
||||
.wi-windy:before {
|
||||
content: "\f021";
|
||||
}
|
||||
.wi-night-alt-cloudy-gusts:before {
|
||||
content: "\f022";
|
||||
}
|
||||
.wi-night-alt-cloudy-windy:before {
|
||||
content: "\f023";
|
||||
}
|
||||
.wi-night-alt-hail:before {
|
||||
content: "\f024";
|
||||
}
|
||||
.wi-night-alt-lightning:before {
|
||||
content: "\f025";
|
||||
}
|
||||
.wi-night-alt-rain-mix:before {
|
||||
content: "\f026";
|
||||
}
|
||||
.wi-night-alt-rain-wind:before {
|
||||
content: "\f027";
|
||||
}
|
||||
.wi-night-alt-rain:before {
|
||||
content: "\f028";
|
||||
}
|
||||
.wi-night-alt-showers:before {
|
||||
content: "\f029";
|
||||
}
|
||||
.wi-night-alt-snow:before {
|
||||
content: "\f02a";
|
||||
}
|
||||
.wi-night-alt-sprinkle:before {
|
||||
content: "\f02b";
|
||||
}
|
||||
.wi-night-alt-storm-showers:before {
|
||||
content: "\f02c";
|
||||
}
|
||||
.wi-night-alt-thunderstorm:before {
|
||||
content: "\f02d";
|
||||
}
|
||||
.wi-night-clear:before {
|
||||
content: "\f02e";
|
||||
}
|
||||
.wi-night-cloudy-gusts:before {
|
||||
content: "\f02f";
|
||||
}
|
||||
.wi-night-cloudy-windy:before {
|
||||
content: "\f030";
|
||||
}
|
||||
.wi-night-cloudy:before {
|
||||
content: "\f031";
|
||||
}
|
||||
.wi-night-hail:before {
|
||||
content: "\f032";
|
||||
}
|
||||
.wi-night-lightning:before {
|
||||
content: "\f033";
|
||||
}
|
||||
.wi-night-rain-mix:before {
|
||||
content: "\f034";
|
||||
}
|
||||
.wi-night-rain-wind:before {
|
||||
content: "\f035";
|
||||
}
|
||||
.wi-night-rain:before {
|
||||
content: "\f036";
|
||||
}
|
||||
.wi-night-showers:before {
|
||||
content: "\f037";
|
||||
}
|
||||
.wi-night-snow:before {
|
||||
content: "\f038";
|
||||
}
|
||||
.wi-night-sprinkle:before {
|
||||
content: "\f039";
|
||||
}
|
||||
.wi-night-storm-showers:before {
|
||||
content: "\f03a";
|
||||
}
|
||||
.wi-night-thunderstorm:before {
|
||||
content: "\f03b";
|
||||
}
|
||||
.wi-celcius:before {
|
||||
content: "\f03c";
|
||||
}
|
||||
.wi-cloud-down:before {
|
||||
content: "\f03d";
|
||||
}
|
||||
.wi-cloud-refresh:before {
|
||||
content: "\f03e";
|
||||
}
|
||||
.wi-cloud-up:before {
|
||||
content: "\f040";
|
||||
}
|
||||
.wi-cloud:before {
|
||||
content: "\f041";
|
||||
}
|
||||
.wi-degrees:before {
|
||||
content: "\f042";
|
||||
}
|
||||
.wi-down-left:before {
|
||||
content: "\f043";
|
||||
}
|
||||
.wi-down:before {
|
||||
content: "\f044";
|
||||
}
|
||||
.wi-fahrenheit:before {
|
||||
content: "\f045";
|
||||
}
|
||||
.wi-horizon-alt:before {
|
||||
content: "\f046";
|
||||
}
|
||||
.wi-horizon:before {
|
||||
content: "\f047";
|
||||
}
|
||||
.wi-left:before {
|
||||
content: "\f048";
|
||||
}
|
||||
.wi-lightning:before {
|
||||
content: "\f016";
|
||||
}
|
||||
.wi-night-fog:before {
|
||||
content: "\f04a";
|
||||
}
|
||||
.wi-refresh-alt:before {
|
||||
content: "\f04b";
|
||||
}
|
||||
.wi-refresh:before {
|
||||
content: "\f04c";
|
||||
}
|
||||
.wi-right:before {
|
||||
content: "\f04d";
|
||||
}
|
||||
.wi-sprinkles:before {
|
||||
content: "\f04e";
|
||||
}
|
||||
.wi-strong-wind:before {
|
||||
content: "\f050";
|
||||
}
|
||||
.wi-sunrise:before {
|
||||
content: "\f051";
|
||||
}
|
||||
.wi-sunset:before {
|
||||
content: "\f052";
|
||||
}
|
||||
.wi-thermometer-exterior:before {
|
||||
content: "\f053";
|
||||
}
|
||||
.wi-thermometer-internal:before {
|
||||
content: "\f054";
|
||||
}
|
||||
.wi-thermometer:before {
|
||||
content: "\f055";
|
||||
}
|
||||
.wi-tornado:before {
|
||||
content: "\f056";
|
||||
}
|
||||
.wi-up-right:before {
|
||||
content: "\f057";
|
||||
}
|
||||
.wi-up:before {
|
||||
content: "\f058";
|
||||
}
|
||||
.wi-wind-east:before {
|
||||
content: "\f059";
|
||||
}
|
||||
.wi-wind-north-east:before {
|
||||
content: "\f05a";
|
||||
}
|
||||
.wi-wind-north-west:before {
|
||||
content: "\f05b";
|
||||
}
|
||||
.wi-wind-north:before {
|
||||
content: "\f05c";
|
||||
}
|
||||
.wi-wind-south-east:before {
|
||||
content: "\f05d";
|
||||
}
|
||||
.wi-wind-south-west:before {
|
||||
content: "\f05e";
|
||||
}
|
||||
.wi-wind-south:before {
|
||||
content: "\f060";
|
||||
}
|
||||
.wi-wind-west:before {
|
||||
content: "\f061";
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 338 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 383 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 401 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,121 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="weather_iconsregular" horiz-adv-x="2548" >
|
||||
<font-face units-per-em="2048" ascent="1755" descent="-293" />
|
||||
<missing-glyph horiz-adv-x="685" />
|
||||
<glyph horiz-adv-x="2048" />
|
||||
<glyph horiz-adv-x="2048" />
|
||||
<glyph unicode="
" horiz-adv-x="2048" />
|
||||
<glyph unicode=" " horiz-adv-x="685" />
|
||||
<glyph unicode="	" horiz-adv-x="685" />
|
||||
<glyph unicode=" " horiz-adv-x="685" />
|
||||
<glyph unicode=" " horiz-adv-x="1122" />
|
||||
<glyph unicode=" " horiz-adv-x="2245" />
|
||||
<glyph unicode=" " horiz-adv-x="1122" />
|
||||
<glyph unicode=" " horiz-adv-x="2245" />
|
||||
<glyph unicode=" " horiz-adv-x="748" />
|
||||
<glyph unicode=" " horiz-adv-x="561" />
|
||||
<glyph unicode=" " horiz-adv-x="374" />
|
||||
<glyph unicode=" " horiz-adv-x="374" />
|
||||
<glyph unicode=" " horiz-adv-x="280" />
|
||||
<glyph unicode=" " horiz-adv-x="449" />
|
||||
<glyph unicode=" " horiz-adv-x="124" />
|
||||
<glyph unicode=" " horiz-adv-x="449" />
|
||||
<glyph unicode=" " horiz-adv-x="561" />
|
||||
<glyph unicode="" horiz-adv-x="571" d="M0 0z" />
|
||||
<glyph unicode="" d="M-287 90q0 -38 29 -64q27 -27 65 -27h627q41 0 72.5 -30t31.5 -73t-31.5 -74t-72.5 -31t-73 32q-29 26 -65 26q-38 0 -64 -25.5t-26 -63.5t26 -64q85 -85 202 -85q118 0 201 83.5t83 201.5t-83 202t-201 84h-627q-38 0 -66 -27.5t-28 -64.5zM-287 411q0 -35 29 -61 q27 -27 65 -27h1170q118 0 201.5 83.5t83.5 201.5t-83 200t-202 82q-121 0 -201 -81q-25 -26 -25 -65t24.5 -63.5t63.5 -24.5q38 0 66 25q30 30 72 30t72.5 -30t30.5 -73t-30.5 -74t-72.5 -31h-1170q-38 0 -66 -27.5t-28 -64.5zM-3 662q0 -13 17 -13h153q12 0 22 15 q36 87 111.5 143.5t169.5 63.5l56 8q20 0 20 18l7 55q17 173 146 289t304 116q176 0 305.5 -115.5t147.5 -289.5l7 -62q0 -19 19 -19h174q144 0 245.5 -100.5t101.5 -242.5q0 -143 -101.5 -244.5t-245.5 -101.5h-736q-19 0 -19 -19v-146q0 -18 19 -18h736q143 0 264.5 71 t192 193t70.5 265q0 118 -45 216q121 159 121 353q0 150 -75 279t-204 204.5t-279 75.5q-248 0 -413 -185q-128 65 -285 65q-225 0 -398 -139.5t-220 -356.5q-136 -32 -240.5 -131t-145.5 -234v-4q-2 -3 -2 -9zM869 1838q0 -38 28 -64l65 -69q26 -26 65 -26q40 0 65.5 24.5 t25.5 64.5q0 38 -24 64l-70 69q-25 28 -63 28t-65 -26.5t-27 -64.5zM1437 1368q115 109 264 109q155 0 267 -112t112 -268q0 -104 -55 -195q-153 153 -369 153h-35q-38 173 -184 313zM1609 1927q0 -37 27 -62.5t65 -25.5t64.5 25.5t26.5 62.5v218q0 38 -26.5 65t-64.5 27 t-65 -27t-27 -65v-218zM2201 1685q0 -39 24 -64q27 -27 65 -27.5t61 27.5l156 153q27 27 27 65q0 37 -27 64t-65 27t-64 -26l-153 -157q-24 -25 -24 -62zM2283 423q0 -37 27 -64l68 -69q32 -26 67 -26q30 0 62 26q27 27 27 64q0 35 -27 65l-68 69q-26 26 -62 26 q-40 0 -67 -26.5t-27 -64.5zM2445 1097q0 -39 26 -63q24 -28 62 -28h216q37 0 64 27t27 64q0 38 -27 65t-64 27h-216q-38 0 -63 -27t-25 -65z" />
|
||||
<glyph unicode="" d="M-253 94q0 -38 27 -65q70 -29 93 -29h840q38 0 65 27.5t27 65.5q0 37 -27 62.5t-65 25.5h-840q-42 0 -81 -25.5t-39 -61.5zM-104 414q0 -38 27 -63q24 -28 62 -28h1004q38 0 64.5 26.5t26.5 64.5t-26.5 65t-64.5 27h-1004q-37 0 -63 -27t-26 -65zM8 667q0 -14 18 -14h149 q19 0 23 14q41 85 115.5 140.5t168.5 66.5h59q17 0 17 20l8 60q16 173 146 290t306 117q174 0 304.5 -117t148.5 -290l8 -60q0 -20 18 -20h172q142 0 245 -102t103 -242q0 -144 -102.5 -246.5t-245.5 -102.5h-735q-19 0 -19 -20v-142q0 -19 19 -19h735q144 0 266 71t193 193 t71 266q0 114 -47 214q125 155 125 350q0 150 -76 279t-205.5 204.5t-280.5 75.5q-117 0 -223.5 -47.5t-185.5 -133.5q-132 69 -288 69q-226 0 -401 -140t-223 -358q-136 -34 -239.5 -133.5t-144.5 -235.5q-2 -2 -2 -7zM85 -246q0 -39 27 -63q26 -27 63 -27h1004 q37 0 63.5 26.5t26.5 63.5q0 40 -26 66.5t-64 26.5h-1004q-38 0 -64 -26.5t-26 -66.5zM882 1835q0 -39 27 -64l67 -70q26 -26 64 -26q41 0 67 25.5t26 65.5q0 36 -27 63l-68 69q-27 27 -62 27q-40 0 -67 -26.5t-27 -63.5zM1455 1368q106 101 260 101q156 0 265.5 -109.5 t109.5 -265.5q0 -107 -49 -193q-151 152 -372 152h-32q-46 184 -182 315zM1625 1925q0 -38 26.5 -63t63.5 -25q40 0 65 25t25 63v218q0 39 -25.5 65.5t-64.5 26.5q-37 0 -63.5 -27t-26.5 -65v-218zM2215 1681q0 -39 26 -64q20 -26 64 -26q43 0 63 26l157 154q26 24 26 66 q0 37 -27 63.5t-65 26.5t-65 -25l-153 -158q-26 -25 -26 -63zM2299 416q0 -38 26 -64l69 -67q39 -29 65 -29q27 0 66 29q26 26 26 64q0 37 -26 65l-69 65q-30 28 -69 28q-38 0 -63 -26t-25 -65zM2454 1090q0 -40 28 -65q29 -27 64 -27h217q36 0 63 27t27 65q0 36 -26.5 60.5 t-63.5 24.5h-217q-39 0 -65.5 -24.5t-26.5 -60.5z" />
|
||||
<glyph unicode="" d="M8 528q0 -144 70.5 -266t191.5 -192.5t264 -70.5h1155q143 0 265 70.5t193 192.5t71 266q0 106 -45 213q122 149 122 353q0 114 -44 217.5t-119 178.5t-178.5 119t-217.5 44q-237 0 -414 -186q-124 70 -288 70q-225 0 -398 -139.5t-222 -357.5q-179 -41 -292.5 -184 t-113.5 -328zM190 528q0 134 89.5 231t224.5 113l53 3q20 0 20 19l7 58q22 173 150 289.5t300 116.5q176 0 306.5 -117t146.5 -289l8 -62q4 -18 22 -18h172q141 0 243 -102t102 -242q0 -145 -101.5 -247.5t-243.5 -102.5h-1155q-140 0 -242 103.5t-102 246.5zM905 1837 q0 -39 26 -67l70 -68q40 -30 68 -27q33 0 59 27.5t26 66.5t-28 63l-63 70q-29 26 -65 26q-39 0 -66 -26.5t-27 -64.5zM1475 1365q111 107 261 107q158 0 268.5 -110t110.5 -268q0 -100 -54 -196q-155 153 -372 153h-34q-40 174 -180 314zM1648 1928q0 -41 25 -66t63 -25 q41 0 66 25t25 66v218q0 38 -25.5 63t-65.5 25q-38 0 -63 -25t-25 -63v-218zM2237 1683q0 -41 24 -66q34 -26 66 -26q29 0 63 26l153 153q26 29 26 68q0 38 -26 64t-63 26q-38 0 -62 -26l-157 -153q-24 -28 -24 -66zM2322 421q0 -38 27 -67l69 -67q24 -26 62 -26t63.5 26.5 t25.5 66.5q0 36 -26 62l-69 69q-26 26 -61 26q-38 0 -64.5 -26t-26.5 -64zM2478 1094q0 -37 28 -62q26 -26 65 -26h218q37 0 61.5 25t24.5 63t-24.5 64.5t-61.5 26.5h-218q-38 0 -65.5 -27t-27.5 -64z" />
|
||||
<glyph unicode="" d="M-290 85q0 -38 26.5 -63t66.5 -25h1997q38 0 64.5 25.5t26.5 62.5q0 38 -26.5 64.5t-64.5 26.5h-1997q-40 0 -66.5 -26.5t-26.5 -64.5zM-10 419q0 -37 27 -62q27 -29 64 -29h1997q37 0 62.5 26.5t25.5 64.5q0 37 -25 62.5t-63 25.5h-1997q-38 0 -64.5 -25.5t-26.5 -62.5z M2 675q0 -14 17 -14h154q10 0 21 17q38 83 113.5 136t166.5 60l59 8q18 0 18 19l7 54q17 173 146.5 289t304.5 116q173 0 302 -115t147 -286l8 -62q0 -18 21 -18h171q103 0 187.5 -55t125.5 -146q11 -17 22 -17h153q22 0 15 24l-22 59q122 151 122 353q0 113 -44 216 t-118 178t-178 119t-218 44q-247 0 -408 -179q-135 67 -286 67q-224 0 -399 -141t-224 -359q-284 -75 -381 -357q-3 -5 -3 -10zM176 -243q0 -38 29 -64q25 -28 62 -28h1999q38 0 65 27.5t27 64.5t-27 61.5t-65 24.5h-1999q-38 0 -64.5 -24.5t-26.5 -61.5zM877 1834 q0 -38 25 -63l68 -68q27 -29 63 -29t63 26.5t27 65.5t-26 67l-68 65q-26 28 -64 28q-39 0 -63.5 -26.5t-24.5 -65.5zM1443 1367q108 108 260 108q157 0 267.5 -111t110.5 -267q0 -104 -52 -192q-152 152 -371 152h-35q-44 186 -180 310zM1615 1925q0 -37 25.5 -62.5 t62.5 -25.5q40 0 67 25.5t27 62.5v218q0 37 -28 64t-66 27q-37 0 -62.5 -26.5t-25.5 -64.5v-218zM2201 1682q0 -37 25 -64q59 -58 132 0l152 153q26 28 26 68q0 37 -26 63t-63 26q-38 0 -64 -26l-157 -157q-25 -27 -25 -63zM2287 424q0 -38 27 -64l69 -69q26 -26 62 -26 q33 0 65 26q26 28 26 68q0 36 -26 60l-69 70q-28 26 -64 26q-38 0 -64 -26.5t-26 -64.5zM2445 1097q0 -39 28 -64q24 -27 63 -27h218q37 0 62.5 26.5t25.5 64.5t-25.5 64t-62.5 26h-218q-38 0 -64.5 -26.5t-26.5 -63.5z" />
|
||||
<glyph unicode="" d="M1 530q0 -214 149 -367.5t363 -163.5q20 0 20 18v143q0 19 -20 19q-137 7 -233.5 109.5t-96.5 241.5q0 133 90.5 231t224.5 114l57 4q21 0 21 19l7 59q17 173 146.5 289.5t305.5 116.5q174 0 305.5 -116.5t149.5 -289.5l8 -62q0 -20 19 -20h172q143 0 247.5 -102.5 t104.5 -242.5q0 -139 -97 -241.5t-234 -109.5q-21 0 -21 -19v-143q0 -18 21 -18q214 7 362.5 161.5t148.5 369.5q0 116 -45 214q126 154 126 355q0 151 -75.5 280.5t-205 205.5t-280.5 76q-250 0 -416 -187q-128 70 -290 70q-226 0 -401.5 -140t-225.5 -359 q-177 -42 -292 -186t-115 -329zM570 -223q16 -35 49 -48q32 -16 67.5 -2.5t47.5 47.5q16 35 2.5 69t-47.5 47q-32 17 -66 3t-50 -50q-16 -28 -3 -66zM639 80q0 -22 10 -41q31 -49 95 -49q51 0 74 69l111 343q13 39 -7.5 71.5t-58.5 39.5q-35 11 -67.5 -6.5t-43.5 -53.5 l-110 -344q-3 -15 -3 -29zM838 -519q0 -21 5 -31q14 -35 48 -48q15 -8 37 -8q10 0 32 6q35 13 50.5 48.5t-0.5 70.5t-48 48.5t-66 -0.5q-31 -12 -44.5 -37.5t-13.5 -48.5zM903 1843q0 -40 26 -64l69 -69q26 -26 58 -29q33 -5 65.5 24.5t32.5 68.5q0 38 -26 64l-67 68 q-30 27 -67 27q-39 0 -65 -26t-26 -64zM917 -232q0 -26 16.5 -51t50.5 -35q18 -4 26 -4q24 0 41 8q32 13 46 61l192 655q11 38 -6 69.5t-53 41.5q-38 11 -70 -6t-43 -54l-197 -660q-3 -15 -3 -25zM1285 -191q0 -22 6 -33q14 -33 48 -47q17 -8 37 -8q10 0 32 6q36 14 49 47 q13 35 0.5 67.5t-44.5 48.5q-36 17 -70.5 3t-51.5 -50q-6 -11 -6 -34zM1361 83q0 -25 16.5 -48.5t49.5 -33.5q13 -3 27 -3q62 0 84 65l110 339q12 37 -7 69t-55 42q-38 11 -68.5 -6t-42.5 -54l-109 -341q-5 -22 -5 -29zM1475 1371q107 103 266 103q156 0 266.5 -109.5 t110.5 -265.5q0 -100 -55 -197q-153 154 -374 154h-33q-47 185 -181 315zM1648 1933q0 -38 27.5 -65t65.5 -27q37 0 62.5 27t25.5 65v220q0 38 -25.5 65t-62.5 27q-38 0 -65.5 -27t-27.5 -65v-220zM2240 1689q0 -39 27 -64q24 -28 61.5 -27.5t64.5 27.5l154 154q29 24 29 64 q0 38 -27.5 65t-65.5 27q-35 0 -61 -29l-155 -153q-27 -25 -27 -64zM2326 419q0 -36 26 -64l70 -67q23 -29 64 -29q38 0 61 29q29 26 29 64t-29 65l-69 66q-25 28 -62 28t-63.5 -27t-26.5 -65zM2482 1099q0 -38 28 -64q28 -28 66 -28h217q38 0 65.5 27t27.5 65 q0 37 -27 62.5t-66 25.5h-217q-40 0 -67 -25.5t-27 -62.5z" />
|
||||
<glyph unicode="" d="M5 528q0 -213 148 -366t362 -163q19 0 19 18v146q0 19 -19 19q-139 11 -234 110.5t-95 235.5q0 134 91 233.5t224 110.5l56 8q20 0 20 18l7 54q17 173 146.5 289.5t304.5 116.5q174 0 304 -116t149 -290l7 -62q0 -18 19 -18h172q145 0 247 -101t102 -243 q0 -136 -95 -235.5t-234 -110.5q-20 0 -20 -19v-146q0 -18 20 -18q213 7 361 161t148 368q0 108 -50 221q126 150 126 349q0 114 -44.5 217.5t-119 178.5t-178 119t-216.5 44q-247 0 -414 -185q-137 66 -284 66q-227 0 -401.5 -139t-223.5 -359q-176 -41 -290.5 -184.5 t-114.5 -327.5zM805 -674h32l566 837q6 7 3 14.5t-14 7.5h-233l244 449q12 23 -14 23h-315q-13 0 -23 -15l-229 -610q-4 -22 15 -22h230zM898 1841q0 -39 27 -66l69 -69q67 -51 129 0q27 30 27 68q0 36 -27 63l-67 69q-30 27 -66 27q-38 0 -65 -27.5t-27 -64.5zM1469 1369 q109 109 264 109q156 0 266 -111t110 -269q0 -97 -54 -193q-156 150 -369 150h-33q-43 182 -184 314zM1641 1933q0 -40 26 -66t66 -26q38 0 63 25.5t25 66.5v218q0 38 -25 63t-63 25t-65 -25t-27 -63v-218zM2230 1686q0 -38 28 -64q29 -27 60 -27q26 0 66 27l153 153 q28 30 28 67q0 39 -27 65t-65 26q-35 0 -62 -27l-153 -153q-28 -30 -28 -67zM2317 425q0 -37 26 -65l68 -70q26 -26 62 -26q38 0 65 27.5t27 66.5q0 35 -28 61l-65 70q-30 25 -66 25q-38 0 -63.5 -26t-25.5 -63zM2472 1098q0 -36 27 -61q27 -27 64 -27h219q38 0 64.5 25.5 t26.5 62.5q0 38 -27 65t-64 27h-219q-37 0 -64 -27t-27 -65z" />
|
||||
<glyph unicode="" d="M1 523q0 -212 146 -363t360 -161q19 0 19 18v142q0 19 -19 19q-137 7 -231 106.5t-94 238.5q0 135 90 234t224 110l56 8q17 0 17 15l8 59q20 175 147.5 290t302.5 115t305.5 -115t147.5 -287l7 -62q4 -18 23 -18h171q142 0 244 -102.5t102 -246.5q0 -139 -94 -238.5 t-231 -106.5q-21 0 -21 -19v-142q0 -18 21 -18q213 7 359 159t146 365q0 108 -41 214q124 154 124 357q0 113 -44 216.5t-119 178.5t-178.5 119.5t-217.5 44.5q-246 0 -412 -186q-143 70 -292 70q-226 0 -398.5 -140t-221.5 -360q-180 -41 -293 -184.5t-113 -329.5z M573 -227q0 -27 17 -54t50 -37q37 -11 68.5 4t42.5 60l15 65q8 36 -10 67.5t-55 42.5q-36 11 -68.5 -8t-42.5 -57l-15 -63q-2 -6 -2 -20zM654 82q0 -35 26 -61q25 -27 61 -27q38 0 64 25.5t26 62.5t-26 62.5t-64 25.5q-37 0 -62 -25t-25 -63zM719 325q-2 -25 14 -48.5 t51 -34.5q33 -10 66.5 7.5t44.5 54.5l30 96q12 39 -7.5 69.5t-58.5 41.5q-35 11 -67 -7t-43 -53l-27 -98q-3 -27 -3 -28zM842 -560q0 -27 17 -52.5t52 -35.5q14 -3 26 -3q69 0 85 65l15 63q10 40 -9 72.5t-57 39.5q-34 11 -66.5 -7.5t-43.5 -54.5l-15 -63q-4 -18 -4 -24z M902 1834q0 -38 26 -64l70 -68q22 -25 57.5 -27.5t66.5 27.5q27 27 27 63q0 37 -27 64l-67 69q-25 25 -63 28q-37 0 -63.5 -27t-26.5 -65zM926 -250q0 -36 26 -62t62 -26q38 0 63 25t25 63q0 37 -25 62t-63 25t-63 -25t-25 -62zM992 -8q-2 -24 14.5 -50t48.5 -32 q37 -10 68 6t44 60l28 96q11 35 -7.5 67t-56.5 43q-35 11 -68 -8.5t-44 -56.5l-24 -96q-3 -14 -3 -29zM1287 -237q0 -27 16 -51.5t49 -34.5q5 0 15 -2t15 -2q65 0 81 70l15 64q11 34 -7.5 67t-54.5 44q-39 10 -71.5 -8.5t-43.5 -56.5l-11 -63q0 -2 -1.5 -12t-1.5 -15z M1366 78q0 -37 26 -61q24 -26 62 -26t63 25t25 62q0 38 -25 63t-63 25t-63 -25t-25 -63zM1431 325q0 -27 17.5 -51.5t52.5 -34.5q3 0 12.5 -2t14.5 -2q17 0 39 10q33 17 43 56l27 96q10 36 -8 67.5t-54 42.5q-37 11 -68.5 -6t-42.5 -54l-30 -97q0 -3 -1.5 -11.5t-1.5 -13.5z M1469 1361q106 106 262 106q158 0 269 -108.5t111 -264.5q0 -106 -57 -200q-157 157 -373 157h-33q-45 176 -179 310zM1645 1923q0 -37 24.5 -61.5t61.5 -24.5q39 0 66 24.5t27 61.5v220q0 37 -27.5 64t-65.5 27q-37 0 -61.5 -26.5t-24.5 -64.5v-220zM2233 1681 q0 -40 24 -64q57 -57 129 0l153 153q27 27 27 67q0 38 -26.5 64.5t-64.5 26.5q-37 0 -65 -26l-153 -158q-24 -23 -24 -63zM2317 417q0 -38 28 -63l65 -67q32 -26 65 -26q32 0 64 26q27 25 27 63q0 36 -27 66l-69 65q-24 27 -61 27t-64 -27q-28 -26 -28 -64zM2474 1094 q0 -38 28 -63q29 -29 66 -29h216q37 0 62.5 27t25.5 65t-25.5 64.5t-62.5 26.5h-216q-38 0 -66 -27t-28 -64z" />
|
||||
<glyph unicode="" d="M-3 527q0 -180 106.5 -321.5t274.5 -188.5q16 -2 27 8l124 150q-143 0 -244.5 103.5t-101.5 248.5q0 134 90 231.5t225 113.5l53 3q20 0 20 20l8 58q17 173 147 290t306 117t307 -117t148 -290l7 -63q7 -18 23 -18h174q141 0 243.5 -101.5t102.5 -243.5 q0 -135 -90.5 -236t-220.5 -112q-78 -9 -96 -30l-235 -301q-22 -30 -17 -67t33 -60q24 -27 63.5 -22t63.5 38l206 262q98 10 185.5 56t150.5 116t100 163t37 193q0 117 -44 214q125 151 125 355q0 113 -44.5 217t-120 179t-179.5 120t-218 45q-241 0 -415 -186 q-127 70 -289 70q-226 0 -400.5 -140.5t-221.5 -359.5q-181 -41 -297 -185t-116 -329zM413 -352q12 -35 49 -51q35 -16 71 -1t49 50q15 33 0.5 66.5t-47.5 49.5q-35 16 -70.5 2t-48.5 -49q-13 -41 -3 -67zM606 -59v-12q3 -35 32 -59q28 -24 67 -21t61 31l233 301 q23 29 19.5 67.5t-31.5 60.5q-29 24 -67 20t-64 -33l-230 -299q-20 -25 -20 -56zM661 -578q0 -14 5 -32q14 -35 49 -49q18 -7 38 -7q15 0 33 5q34 13 47 47q16 35 3 71t-47 49q-35 16 -71.5 1.5t-48.5 -48.5q-8 -17 -8 -37zM839 -325v-11q3 -37 34 -62q24 -26 64 -21.5 t64 36.5l442 558q22 32 18.5 68.5t-32.5 62.5q-29 23 -66 18.5t-60 -33.5l-445 -561q-19 -23 -19 -55zM901 1839q0 -39 28 -63l65 -70q25 -25 59 -28q33 -5 65.5 24t32.5 68q0 36 -26 64l-69 69q-24 26 -63 26q-38 0 -65 -26t-27 -64zM1215 -447q0 -19 7 -33q14 -35 48 -49 q17 -8 36 -8q10 0 32 6q36 14 49 49q16 35 3 70.5t-47 48.5q-35 16 -71.5 2t-49.5 -48q-7 -18 -7 -38zM1472 1368q113 103 264 103q158 0 270 -109.5t112 -265.5q0 -106 -55 -198q-155 155 -372 155h-35q-44 184 -184 315zM1645 1929q0 -37 26.5 -62.5t64.5 -25.5 q39 0 66 25.5t27 62.5v221q0 37 -27.5 64t-65.5 27t-64.5 -26.5t-26.5 -64.5v-221zM2240 1686q0 -38 24 -64q28 -27 65.5 -27.5t60.5 27.5l159 154q26 26 26 65q0 37 -27.5 65t-65.5 28q-35 0 -64 -27l-154 -157q-24 -26 -24 -64zM2322 416q0 -37 27 -64l69 -67 q26 -26 59 -29h5q29 0 67 29q26 26 26 62q0 38 -26 67l-70 66q-25 27 -63 27q-40 0 -67 -26.5t-27 -64.5zM2482 1096q0 -37 27 -64q26 -29 64 -29h218q37 0 64 27.5t27 65.5q0 37 -26.5 62.5t-64.5 25.5h-218q-38 0 -64.5 -25.5t-26.5 -62.5z" />
|
||||
<glyph unicode="" d="M5 529q0 -213 148.5 -366.5t363.5 -163.5q18 0 18 18v143q0 18 -18 18q-137 7 -234 109.5t-97 241.5q0 132 91 230t225 114l56 5q20 0 20 18l7 58q17 173 147 290t305 117q174 0 304.5 -117t148.5 -290l8 -61q0 -20 19 -20h172q142 0 246 -102t104 -242 q0 -139 -96 -241.5t-233 -109.5q-21 0 -21 -18v-143q0 -18 21 -18q213 7 361 161.5t148 368.5q0 117 -44 214q124 154 124 353q0 152 -75.5 281.5t-204.5 204.5t-280 75q-248 0 -413 -186q-131 70 -289 70q-226 0 -401.5 -140.5t-224.5 -358.5q-177 -42 -291.5 -185.5 t-114.5 -327.5zM581 -202q0 -27 17 -52.5t52 -35.5q18 -4 30 -4q62 0 81 68l169 627q11 38 -8.5 71t-56.5 40q-35 11 -67.5 -7t-43.5 -54l-169 -630q-4 -16 -4 -23zM858 -531q0 -30 16 -55.5t55 -31.5q18 -4 29 -4q25 0 47.5 18.5t28.5 51.5l256 953q10 37 -7 68.5t-53 42.5 q-37 11 -69.5 -7t-42.5 -54l-256 -953q0 -3 -2 -13.5t-2 -15.5zM904 1840q0 -39 26 -65l70 -70q32 -24 65 -24q34 0 62 25t28 63q0 39 -26 68l-67 69q-29 27 -64 27q-40 0 -67 -27.5t-27 -65.5zM1302 -205q0 -26 16.5 -50.5t49.5 -34.5q18 -4 26 -4q29 0 53.5 15.5 t31.5 52.5l169 627q10 37 -8 68.5t-54 42.5q-38 11 -69.5 -7t-41.5 -54l-169 -630q-4 -18 -4 -26zM1475 1368q113 107 264 107q157 0 267.5 -110.5t110.5 -268.5q0 -100 -55 -197q-155 155 -373 155h-34q-45 185 -180 314zM1648 1928q0 -37 26.5 -62.5t64.5 -25.5 q37 0 62.5 25t25.5 63v219q0 41 -25 67t-63 26q-40 0 -65.5 -26.5t-25.5 -66.5v-219zM2238 1685q0 -39 28 -63q22 -25 59 -27.5t67 27.5l153 153q29 27 29 67q0 39 -27 65t-66 26q-33 0 -62 -27l-153 -154q-28 -27 -28 -67zM2325 421q0 -38 26 -67l68 -67q28 -22 64 -22 l3 -2q36 0 62 26t26 65q0 38 -29 62l-65 70q-29 26 -66 26t-63 -26.5t-26 -64.5zM2480 1096q0 -39 27 -63q28 -28 67 -28h217q37 0 64 26.5t27 64.5t-27 65.5t-64 27.5h-217q-38 0 -66 -27.5t-28 -65.5z" />
|
||||
<glyph unicode="" d="M1 530q0 -213 148.5 -365.5t362.5 -163.5q18 0 18 18v143q0 19 -18 19q-136 7 -231 108.5t-95 240.5q0 133 90 230.5t225 113.5l52 4q21 0 21 19l7 57q17 173 146.5 289.5t304.5 116.5t305 -116.5t146 -289.5l8 -61q0 -19 19 -19h178q140 0 242 -102t102 -242 q0 -136 -95.5 -237t-230.5 -112q-18 0 -18 -19v-143q0 -18 18 -18q140 4 256 76.5t182.5 192t66.5 260.5q0 114 -44 209q121 150 121 350q0 114 -44 217.5t-119 178.5t-178.5 119t-217.5 44q-241 0 -406 -177q-127 68 -291 68q-226 0 -399 -139.5t-220 -357.5 q-180 -41 -296 -184t-116 -328zM579 -184q0 -29 17 -56.5t49 -38.5q31 -11 65.5 6.5t46.5 58.5l26 112q11 33 -7.5 66.5t-54.5 44.5q-40 10 -72 -9t-39 -57l-29 -106q-2 -14 -2 -21zM718 319q0 -61 68 -84q35 -12 68 5.5t44 56.5l27 110q11 33 -7.5 66t-54.5 45 q-39 10 -71 -8.5t-39 -55.5l-32 -109q-3 -14 -3 -26zM848 -522q0 -26 18 -53t52 -38q1 0 10.5 -1.5t15.5 -1.5q22 0 39 8q30 13 44 62l29 106q11 37 -7.5 69.5t-54.5 42.5q-37 11 -69.5 -7.5t-42.5 -54.5l-29 -109q-5 -20 -5 -23zM897 1832q0 -40 28 -66l69 -69 q54 -54 125 0q26 28 26 65t-26 65l-66 70q-26 26 -64 26t-65 -27t-27 -64zM992 -11q0 -27 17 -54t50 -37q37 -11 68 5t43 60l27 108q11 37 -7 69.5t-54 43.5q-40 11 -72.5 -8.5t-39.5 -56.5l-30 -110q-2 -6 -2 -20zM1289 -195q4 -59 68 -88l26 -4q26 0 51 17t35 53l30 108 q10 38 -9.5 70.5t-56.5 39.5q-33 11 -66 -7.5t-44 -54.5l-29 -109zM1438 313q0 -26 16.5 -51.5t48.5 -34.5l27 -3q31 0 55 19t30 50l30 106q11 37 -7.5 69t-54.5 42q-37 11 -68.5 -6.5t-41.5 -53.5l-32 -113q-3 -13 -3 -24zM1473 1365q106 102 256 102q157 0 268.5 -110.5 t111.5 -267.5q0 -88 -51 -188q-153 153 -370 153h-35q-43 180 -180 311zM1638 1923q0 -40 25.5 -65.5t65.5 -25.5t66 25.5t26 65.5v215q0 40 -26 66t-66 26t-65.5 -26t-25.5 -66v-215zM2230 1678q0 -40 24 -65q33 -27 66 -27q30 0 63 27l153 153q26 29 26 67t-26 64t-63 26 t-65 -26l-154 -153q-24 -28 -24 -66zM2314 416q0 -37 28 -67l66 -68q33 -33 66 -33q30 0 62 33q29 29 28 65.5t-28 63.5l-69 70q-26 26 -61 26q-38 0 -65 -26.5t-27 -63.5zM2471 1089q0 -36 26 -62t62 -26h218q41 0 67 25t26 63q0 40 -26.5 66t-66.5 26h-218 q-37 0 -62.5 -27t-25.5 -65z" />
|
||||
<glyph unicode="" d="M1 525q0 -138 68 -257t185.5 -191t256.5 -76q18 0 18 18v142q0 20 -18 20q-136 7 -232.5 108.5t-96.5 235.5q0 132 90.5 230t223.5 114l56 6q19 0 19 20l8 54q17 175 146 291.5t304 116.5q174 0 304 -116.5t147 -288.5l8 -62q0 -18 18 -18h172q144 0 246 -102.5 t102 -244.5q0 -134 -96.5 -235.5t-231.5 -108.5q-20 0 -20 -20v-142q0 -18 20 -18q212 7 360 160t148 364q0 121 -46 217q126 151 126 352q0 150 -75 278.5t-204 203.5t-279 75q-246 0 -413 -185q-130 70 -286 70q-225 0 -399.5 -139.5t-223.5 -356.5q-179 -44 -292 -187 t-113 -328zM678 93q0 -38 25.5 -65t62.5 -27t62.5 27t25.5 65q0 36 -25.5 62t-62.5 26t-62.5 -26t-25.5 -62zM678 -294q0 -33 26 -61q28 -26 62 -26q38 0 63 25t25 62q0 38 -25 63t-63 25t-63 -25t-25 -63zM896 1832q0 -39 26 -63l70 -70q26 -26 57 -27q33 -5 65 23.5 t32 67.5t-26 68l-67 65q-24 27 -63 27q-40 0 -67 -26.5t-27 -64.5zM1017 -112q0 -36 26 -64q26 -26 62 -26q38 0 65 26t27 64q0 37 -27 63.5t-65 26.5q-36 0 -62 -26.5t-26 -63.5zM1017 272q0 -36 26 -62t62 -26q38 0 65 25.5t27 62.5t-27 63t-65 26q-36 0 -62 -26t-26 -63z M1017 -502q0 -35 26 -61q27 -27 62 -27q38 0 65 25t27 63q0 37 -27 64t-65 27q-35 0 -61.5 -27t-26.5 -64zM1361 93q0 -38 26 -65t63 -27t62.5 27t25.5 65q0 36 -25.5 62t-62.5 26t-63 -26t-26 -62zM1361 -294q0 -34 25 -61q28 -26 64 -26q38 0 63 25t25 62q0 38 -25 63 t-63 25t-63.5 -25.5t-25.5 -62.5zM1465 1365q110 106 263 106q155 0 265 -111t110 -266q0 -100 -54 -196q-153 153 -371 153h-33q-47 186 -180 314zM1637 1921q0 -37 26.5 -62t64.5 -25t63 25t25 62v218q0 38 -25.5 65t-62.5 27t-64 -27t-27 -65v-218zM2224 1679 q0 -37 27 -63q24 -25 59.5 -27.5t66.5 27.5l153 153q28 28 28 65q0 38 -27 65t-65 27q-34 0 -61 -27l-154 -156q-27 -25 -27 -64zM2310 421q0 -40 26 -66l69 -67q39 -26 67 -26q33 0 59.5 27.5t26.5 65.5q0 36 -28 62l-66 69q-28 26 -65 26t-63 -26.5t-26 -64.5zM2464 1094 q0 -37 29 -63q27 -29 65 -29h216q37 0 64 27t27 65t-26.5 64.5t-64.5 26.5h-216q-38 0 -66 -27t-28 -64z" />
|
||||
<glyph unicode="" d="M-2 529q0 -139 67.5 -258.5t184.5 -191.5t256 -78q20 0 20 18v142q0 20 -20 20q-136 7 -232 108.5t-96 239.5q0 132 90 229.5t223 113.5l56 3q21 0 21 19l8 58q17 173 145.5 289t303.5 116q172 0 302.5 -116.5t149.5 -288.5l6 -62q0 -18 19 -18h172q141 0 245 -102 t104 -241q0 -138 -96 -239.5t-233 -108.5q-20 0 -20 -20v-142q0 -18 20 -18q139 4 256 76.5t184 192.5t67 259q0 118 -44 213q124 152 124 352q0 151 -75 279.5t-203 203t-278 74.5q-248 0 -413 -185q-131 70 -287 70q-225 0 -399.5 -139.5t-223.5 -356.5 q-176 -42 -290 -185t-114 -326zM627 435q0 -61 45.5 -104t108.5 -43q64 0 106.5 42.5t42.5 104.5q0 40 -37 107.5t-69 105.5q-34 36 -43 45l-38 -43q-43 -46 -79.5 -110t-36.5 -105zM893 1834q0 -41 26 -65l68 -70q68 -51 130 0q26 31 26 68t-26 63l-68 69q-30 27 -65 27 q-39 0 -65 -27t-26 -65zM945 13q0 -105 72.5 -176.5t175.5 -71.5q104 0 176.5 73t72.5 175q0 87 -85 210q-74 97 -136 159q-13 9 -28 24l-25 -24q-57 -52 -136 -157q-87 -121 -87 -212zM1102 719q0 -40 30.5 -69t73.5 -29q41 0 70 29t29 69q0 66 -99 171l-27 -27 q-29 -31 -53 -74t-24 -70zM1462 1365q106 106 263 106q156 0 265 -110t109 -267q0 -96 -54 -196q-154 153 -371 153h-34q-46 186 -178 314zM1633 1926q0 -38 27.5 -65t64.5 -27t61.5 27t24.5 65v217q0 38 -24.5 63t-61.5 25q-38 0 -65 -25t-27 -63v-217zM2221 1679 q0 -39 27 -63q28 -26 59 -26q29 0 66 26l153 153q28 28 28 66q0 39 -26.5 65t-64.5 26q-35 0 -62 -27l-153 -153q-27 -27 -27 -67zM2306 423q0 -40 25 -68l70 -62q23 -29 63 -29q39 0 62 29q28 25 28 62q0 36 -28 62l-65 69q-28 26 -66 26q-37 0 -63 -26t-26 -63zM2461 1094 q0 -36 27 -62q28 -26 66 -26h216q38 0 65 25.5t27 62.5t-27 64t-65 27h-216q-38 0 -65.5 -27t-27.5 -64z" />
|
||||
<glyph unicode="" horiz-adv-x="1971" d="M-282 899q0 -43 30 -71t77 -28h180q43 0 73.5 28.5t30.5 70.5q0 46 -30 76t-74 30h-180q-47 0 -77 -29.5t-30 -76.5zM-94 239q0 -155 113.5 -268.5t268.5 -113.5h731q155 0 265.5 112t110.5 270q0 79 -21 131q133 85 210.5 226.5t77.5 302.5q0 130 -51 248.5t-136.5 204 t-204 136.5t-247.5 51q-175 0 -322.5 -86t-232 -233t-84.5 -321v-36q-160 -91 -211 -266q-121 -38 -194 -135t-73 -223zM73 1750q0 -45 28 -72l172 -180q75 -57 150 0q30 30 30 75q0 43 -30 75l-176 175q-34 31 -74 31q-45 0 -72.5 -30t-27.5 -74zM118 239q0 67 43 115 t109 54l66 9q21 0 21 24l10 60q11 92 77.5 154t157.5 62q93 0 161.5 -62t79.5 -154l10 -69q10 -24 26 -24h140q69 0 120 -50t51 -119q0 -71 -51 -122.5t-120 -51.5h-731q-72 0 -121 51t-49 123zM590 921q11 175 135 294t298 119q178 0 302.5 -127t124.5 -308 q0 -112 -54 -207.5t-147 -154.5q-94 78 -217 78q-47 140 -164.5 223t-265.5 83h-12zM919 1854q0 -44 30.5 -74.5t73.5 -30.5q44 0 74.5 30.5t30.5 74.5v250q0 42 -30.5 70.5t-74.5 28.5q-43 0 -73.5 -28.5t-30.5 -70.5v-250zM1593 230q0 -43 29 -75l175 -173q66 -68 149 0 q29 27 29 72q0 42 -29 71l-179 179q-29 27 -73 27t-72.5 -29t-28.5 -72zM1593 1575q0 -45 29 -77q29 -29 72 -29q44 0 73 29l179 180q29 27 29 72q0 44 -30.5 74t-74.5 30q-42 0 -73 -31l-175 -175q-29 -29 -29 -73zM1869 899q0 -43 30 -71t77 -28h179q43 0 73.5 28.5 t30.5 70.5q0 46 -30 76t-74 30h-179q-47 0 -77 -29.5t-30 -76.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1828" d="M-248 771q0 39 27 66q28 26 64 26h218q37 0 61.5 -27t24.5 -65t-24.5 -64.5t-61.5 -26.5h-218q-37 0 -64 27t-27 64zM57 32q0 37 25 65l157 152q24 25 63 25q38 0 63.5 -24t25.5 -61q0 -39 -26 -68l-152 -152q-65 -51 -131 0q-25 27 -25 63zM57 1509q0 37 25 65 q31 26 68 26q35 0 63 -26l152 -157q26 -24 26 -63q0 -38 -25.5 -63.5t-63.5 -25.5q-39 0 -63 26l-157 152q-25 27 -25 66zM329 771q0 149 75 277.5t203.5 203.5t277.5 75q112 0 215 -44.5t177.5 -119t118.5 -177.5t44 -215q0 -150 -74.5 -278t-202.5 -202.5t-278 -74.5 t-278 74.5t-203 202.5t-75 278zM510 771q0 -156 109.5 -266.5t265.5 -110.5t266.5 110.5t110.5 266.5q0 154 -110.5 263t-266.5 109q-155 0 -265 -109t-110 -263zM794 -58q0 38 26.5 64t64.5 26q39 0 65 -26t26 -64v-212q0 -39 -26.5 -66t-64.5 -27t-64.5 27t-26.5 66v212z M794 1595v218q0 37 27 64t64 27t64 -27t27 -64v-218q0 -37 -26.5 -61.5t-64.5 -24.5t-64.5 24.5t-26.5 61.5zM1383 189q0 37 24 60q24 25 60 25q39 0 64 -25l156 -152q26 -28 26 -65t-26 -63q-64 -50 -128 0l-152 152q-24 27 -24 68zM1383 1354q0 40 24 63l152 157 q28 26 63 26q38 0 64.5 -27t26.5 -64q0 -40 -26 -66l-156 -152q-29 -26 -64 -26q-36 0 -60 25.5t-24 63.5zM1624 771q0 38 26 66q26 26 61 26h216q37 0 64.5 -27.5t27.5 -64.5t-27.5 -64t-64.5 -27h-216q-37 0 -62 26.5t-25 64.5z" />
|
||||
<glyph unicode="" d="M-1 530q0 -179 106.5 -320t275.5 -188l-70 -181q-8 -23 15 -23h227l-152 -449h31l465 604q6 7 1.5 14.5t-15.5 7.5h-233l265 496q12 23 -14 23h-316q-15 0 -25 -16l-114 -307q-115 29 -190 123.5t-75 215.5q0 135 90 233t225 114l54 3q19 0 24 15l8 63 q17 173 146.5 290.5t305.5 117.5q174 0 305.5 -117.5t149.5 -290.5l8 -63q0 -18 18 -18h173q143 0 246 -102.5t103 -244.5q0 -139 -95.5 -241.5t-232.5 -109.5q-21 0 -21 -19v-143q0 -18 21 -18q141 4 258.5 76.5t185.5 193t68 261.5q0 117 -46 215q122 154 122 351 q0 152 -75.5 281.5t-205 205t-281.5 75.5q-115 0 -224 -48t-188 -133q-129 69 -289 69q-227 0 -402.5 -140.5t-224.5 -359.5q-177 -41 -292.5 -186t-115.5 -330zM872 -528q0 -24 17 -50t49 -36q18 -4 27 -4q24 0 41 8q33 13 45 61l30 110q10 40 -9 71.5t-57 39.5 q-33 11 -66 -8t-45 -55l-27 -111q-5 -22 -5 -26zM897 1841q0 -38 26 -64l70 -70q25 -25 58 -28q33 -5 65.5 24t32.5 68q0 37 -27 64l-67 70q-26 26 -64 26q-40 0 -67 -26t-27 -64zM1015 -16q-1 -26 15 -50.5t51 -34.5q34 -11 66.5 6.5t44.5 59.5l32 110q11 35 -8.5 67.5 t-57.5 43.5q-36 11 -68.5 -7.5t-43.5 -56.5l-27 -112q-4 -18 -4 -26zM1317 -195q0 -23 11 -42q21 -34 58 -46q18 -6 30 -6q20 0 33 8q32 12 48 64l26 108q11 38 -6.5 69.5t-53.5 41.5q-37 11 -69.5 -7t-43.5 -54l-30 -111q-3 -14 -3 -25zM1463 319q0 -28 17.5 -53.5 t52.5 -35.5q27 -9 65 5q31 13 45 61l30 107q10 40 -8.5 71.5t-56.5 39.5q-36 11 -68 -6.5t-43 -53.5l-31 -113q-3 -21 -3 -22zM1474 1369q107 103 261 103q157 0 267.5 -109.5t110.5 -266.5q0 -105 -50 -193q-154 154 -375 154h-33q-47 190 -181 312zM1643 1931 q0 -38 27 -65t65 -27t63.5 26.5t25.5 65.5v220q0 39 -25.5 65.5t-63.5 26.5t-65 -27t-27 -65v-220zM2239 1687q0 -39 25 -64q22 -25 58.5 -27.5t67.5 27.5l154 154q27 25 27 64t-27 64q-26 28 -64 28q-37 0 -62 -28l-154 -154q-25 -25 -25 -64zM2322 416q0 -37 27 -64 l69 -67q29 -27 65 -27l3 -2q35 0 58 29q27 26 27 64t-27 65l-66 66q-29 29 -65 29q-38 0 -64.5 -27.5t-26.5 -65.5zM2478 1096q0 -39 28 -63q25 -28 64 -28h220q38 0 65 26.5t27 64.5t-26.5 63.5t-65.5 25.5h-220q-39 0 -65.5 -25.5t-26.5 -63.5z" />
|
||||
<glyph unicode="" d="M-1 528q0 -177 105 -316t274 -190l-68 -181q-7 -22 15 -22h226l-133 -421h31l445 575q6 7 1.5 14.5t-15.5 7.5h-232l264 494q11 23 -15 23h-314q-15 0 -25 -15l-115 -307q-114 29 -189 124t-75 214q0 133 91 231t225 114l56 7q20 0 20 19l7 54q17 173 147 290t305 117 q173 0 303.5 -117t149.5 -290l7 -62q0 -18 19 -18h172q145 0 247.5 -101t102.5 -244q0 -136 -95 -235.5t-234 -110.5q-21 0 -21 -19v-146q0 -18 21 -18q213 7 361 161t148 368q0 120 -45 214q125 151 125 354q0 150 -75.5 279t-204.5 204.5t-280 75.5q-246 0 -413 -185 q-129 69 -288 69q-226 0 -401 -140t-224 -358q-177 -41 -291.5 -184.5t-114.5 -328.5zM862 -494q-2 -24 14.5 -47t49.5 -35q10 -3 21 -3q27 0 54.5 16t36.5 50l244 914q10 37 -7 68.5t-52 42.5q-37 11 -69.5 -7t-42.5 -54l-246 -917q-3 -13 -3 -28zM897 1837q0 -39 26 -63 l69 -70q27 -27 65 -27.5t61 27.5q29 23 29 64q0 39 -26 63l-67 70q-28 26 -65 26q-40 0 -66 -26t-26 -64zM1305 -168q0 -19 12 -40q20 -32 53 -46q11 -5 32 -5q24 0 35 6q32 13 44 62l159 592q10 38 -8 69t-54 42q-37 11 -69 -7t-42 -54l-158 -595q0 -4 -2 -12t-2 -12z M1467 1367q107 103 264 103q156 0 267 -109t111 -265q0 -100 -55 -197q-159 157 -373 157h-33q-49 186 -181 311zM1640 1927q0 -38 27 -65t64 -27q38 0 63 27t25 65v219q0 38 -25 65t-63 27q-37 0 -64 -27t-27 -65v-219zM2230 1683q0 -39 28 -64q23 -27 60.5 -27t64.5 27 l154 155q28 25 28 63t-27 65t-65 27q-36 0 -62 -28l-153 -154q-28 -25 -28 -64zM2315 418q0 -35 27 -64l69 -67q20 -23 59 -26l2 -1q1 0 4 -0.5t5 -0.5q30 0 56 28q28 26 28 64q0 37 -28 65l-70 65q-26 29 -61 29q-37 0 -64 -27t-27 -65zM2471 1096q0 -38 28 -64 q29 -29 66 -29h217q37 0 64.5 27.5t27.5 65.5q0 37 -27 62.5t-65 25.5h-217q-40 0 -67 -25.5t-27 -62.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2194" d="M-231 90q0 39 28 67q28 26 64 26h577q118 0 201.5 -84.5t83.5 -202.5q0 -119 -83 -202.5t-202 -83.5t-203 84q-25 25 -25 64t24.5 64.5t64.5 25.5q38 0 66 -26q32 -31 73 -31q42 0 73 30.5t31 74.5q0 42 -31 72.5t-73 30.5h-577q-38 0 -65 27t-27 64zM-231 414 q0 38 28 66q28 26 64 26h1124q42 0 73 31t31 74t-31 73.5t-73 30.5q-44 0 -73 -30q-28 -24 -67 -24t-63.5 24.5t-24.5 63.5q0 40 24 65q81 81 204 81q119 0 202.5 -83t83.5 -201t-83.5 -201.5t-202.5 -83.5h-1124q-38 0 -65 25.5t-27 62.5zM-2 666q0 -13 17 -13h154 q13 0 23 16q36 87 112 144t170 64l56 8q21 0 21 18l8 55q17 173 146.5 290.5t305.5 117.5q177 0 307 -116.5t148 -291.5l8 -63q0 -18 19 -18h172q145 0 248.5 -102t103.5 -245t-103.5 -245t-248.5 -102h-737q-19 0 -19 -18v-148q0 -18 19 -18h737q145 0 267.5 71t194 193.5 t71.5 266.5q0 145 -71.5 267t-194 193t-267.5 71h-33q-50 213 -223.5 349t-397.5 136q-226 0 -400 -140.5t-221 -359.5q-137 -32 -243 -131.5t-147 -235.5v-4q-2 -5 -2 -9z" />
|
||||
<glyph unicode="" horiz-adv-x="2194" d="M-352 87q0 39 27 65t67 26h957q38 0 63 -25.5t25 -65.5q0 -38 -25.5 -63.5t-62.5 -25.5h-957q-40 0 -67 25.5t-27 63.5zM-71 413q0 38 29 64q23 24 63 24h960q37 0 61.5 -25t24.5 -63t-24.5 -65t-61.5 -27h-960q-37 0 -64.5 27.5t-27.5 64.5zM-5 662q0 -15 18 -15h152 q15 0 25 15q36 87 111 144t168 64l58 7q18 0 18 19l7 55q18 174 148.5 290t306.5 116q174 0 302 -114.5t150 -288.5l8 -63q0 -17 19 -17h171q145 0 247.5 -102t102.5 -247q0 -140 -104 -243.5t-246 -103.5h-735q-19 0 -19 -18v-143q0 -19 19 -19h735q108 0 206.5 41.5 t169 112.5t112.5 168.5t42 204.5q0 144 -70.5 265.5t-192.5 192t-267 70.5h-33q-52 215 -224.5 351.5t-392.5 136.5q-227 0 -401.5 -141.5t-221.5 -361.5q-138 -31 -242 -129.5t-145 -236.5v-2q-2 -4 -2 -8zM117 -243q0 39 28 64q24 25 63 25h959q39 0 65.5 -25.5 t26.5 -63.5t-27 -65t-65 -27h-959q-37 0 -64 27t-27 65z" />
|
||||
<glyph unicode="" horiz-adv-x="2377" d="M3 454q0 159 99.5 282.5t254.5 158.5q41 188 189.5 307.5t342.5 119.5q189 0 337.5 -116.5t192.5 -298.5h29q188 0 321.5 -132.5t133.5 -320.5q0 -123 -61 -228t-166 -166t-228 -61h-990q-92 0 -176.5 36t-145.5 97t-97 145.5t-36 176.5zM159 454q0 -122 87.5 -209.5 t211.5 -87.5h990q124 0 212.5 87.5t88.5 209.5t-88.5 209t-212.5 87h-147q-16 0 -16 16l-7 52q-16 151 -127 250.5t-262 99.5t-262 -100t-125 -250l-7 -45q0 -16 -17 -16l-48 -7q-115 -10 -193 -95t-78 -201zM1103 1384q-16 -15 8 -22q66 -29 114 -59q18 -5 24 3 q97 92 226 92q130 0 224.5 -86.5t105.5 -213.5l10 -68h151q104 0 178.5 -74.5t74.5 -177.5q0 -96 -65.5 -167t-162.5 -82q-16 0 -16 -17v-121q0 -17 16 -17q161 10 272 127t111 277q0 169 -119.5 288.5t-288.5 119.5h-16q-42 160 -175.5 263.5t-299.5 103.5 q-225 0 -372 -169z" />
|
||||
<glyph unicode="" horiz-adv-x="2171" d="M-294 86q0 39 27 65t67 26h1991q40 0 65.5 -25.5t25.5 -65.5q0 -37 -26.5 -62t-64.5 -25h-1991q-40 0 -67 25t-27 62zM-15 421q0 38 29 64q24 24 63 24h1992q37 0 61.5 -25t24.5 -63t-25 -64.5t-61 -26.5h-1992q-38 0 -65 27t-27 64zM-1 675q0 -14 16 -14h153q11 0 22 17 q38 83 113.5 136t165.5 60l58 8q18 0 18 19l7 53q17 173 146.5 288.5t303.5 115.5q173 0 301.5 -114t146.5 -286l8 -61q0 -18 21 -18h170q103 0 187.5 -55t125.5 -146q11 -17 22 -17h153q19 0 15 24q-47 164 -186 268t-317 104h-34q-53 213 -223.5 348.5t-389.5 135.5 q-224 0 -397.5 -140.5t-222.5 -358.5q-136 -32 -239 -129t-143 -232v4q-1 -3 -1 -10zM171 -241q0 38 28 63q24 24 64 24h1993q38 0 64.5 -25t26.5 -62q0 -38 -27 -65t-64 -27h-1993q-37 0 -64.5 27.5t-27.5 64.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2211" d="M2 528q0 -213 148.5 -366t362.5 -163q18 0 18 18v143q0 18 -18 18q-137 7 -233 109t-96 241q0 132 90 230t223 114l57 3q21 0 21 20l7 57q17 173 146 289.5t304 116.5q174 0 304.5 -116.5t148.5 -289.5l8 -62q0 -18 18 -18h172q142 0 246 -102t104 -242 q0 -139 -96.5 -241t-232.5 -109q-21 0 -21 -18v-143q0 -18 21 -18q104 3 198.5 46.5t162.5 114t108 167t40 201.5q0 143 -71.5 263.5t-193.5 190t-265 69.5h-34q-52 214 -224.5 350t-392.5 136q-225 0 -400 -139.5t-224 -357.5q-177 -41 -291.5 -184.5t-114.5 -327.5z M583 -240q15 -34 49 -49q32 -16 66.5 -2t47.5 48q16 35 3 68.5t-48 46.5q-32 17 -66 3t-50 -50q-15 -26 -2 -65zM650 61q0 -25 17 -48.5t50 -34.5q31 -18 66 -1.5t47 63.5l96 361q10 40 -8.5 71.5t-56.5 38.5q-13 3 -27 3q-25 0 -49.5 -16t-34.5 -47l-95 -362q-5 -22 -5 -28 zM849 -535q0 -19 6 -31q14 -35 48 -48q15 -8 35 -8q10 0 32 6q36 13 51.5 48t-0.5 70t-48 49t-67 0q-30 -13 -43.5 -38t-13.5 -48zM927 -257q0 -59 67 -78q18 -4 27 -4q24 0 41 8q32 12 44 61l179 671q10 38 -7 69t-53 41q-14 3 -28 3q-27 0 -52.5 -16t-31.5 -47l-182 -676 q-4 -22 -4 -32zM1294 -208q0 -19 8 -34q13 -31 47 -47q18 -7 36 -7q10 0 32 6q34 13 49 47q12 35 -0.5 67t-44.5 48q-36 17 -69.5 3t-49.5 -50q-8 -15 -8 -33zM1370 66q0 -23 17 -48t48 -35q25 -5 29 -5q15 0 39 11q32 15 43 56l96 356q0 3 2 13t2 15q0 25 -16.5 49 t-48.5 33q-14 3 -29 3q-26 0 -49.5 -15.5t-32.5 -47.5l-96 -358q0 -3 -2 -12t-2 -15z" />
|
||||
<glyph unicode="" horiz-adv-x="1371" d="M-62 -283h43l733 1086q15 29 -16 29h-303l319 581q14 29 -20 29h-407q-17 0 -31 -19l-296 -789q-4 -29 21 -29h292zM846 392h28l557 818q8 13 4 21t-18 8h-224l233 430q19 32 -19 32h-292q-21 0 -32 -20l-221 -585q-10 -30 20 -30h219z" />
|
||||
<glyph unicode="" horiz-adv-x="2211" d="M-5 522q0 -211 149 -364t361 -160q20 0 20 18v142q0 19 -20 19q-135 7 -232 108.5t-97 236.5q0 134 90.5 233.5t223.5 110.5l56 8q21 0 21 19l8 53q16 175 145 293t305 118q173 0 303.5 -117t149.5 -289l7 -62q0 -19 19 -19h171q144 0 247 -103t103 -245 q0 -135 -96.5 -236.5t-232.5 -108.5q-21 0 -21 -19v-142q0 -18 21 -18q213 7 361 159.5t148 364.5q0 143 -71.5 264.5t-193.5 192t-265 70.5h-33q-53 214 -225 350.5t-392 136.5q-225 0 -400 -140t-224 -357q-180 -46 -293 -188.5t-113 -328.5zM573 -227q0 -27 17 -54 t50 -37q37 -11 68.5 4t42.5 60l15 65q8 36 -10 67.5t-55 42.5q-36 11 -68.5 -8t-42.5 -57l-15 -63q-2 -6 -2 -20zM654 82q0 -35 26 -61q25 -27 61 -27q38 0 64 25.5t26 62.5t-26 62.5t-64 25.5q-37 0 -62 -25t-25 -63zM719 325q-2 -25 14 -48.5t51 -34.5q33 -10 66.5 7.5 t44.5 54.5l30 96q12 39 -7.5 69.5t-58.5 41.5q-35 11 -67 -7t-43 -53l-27 -98q-3 -27 -3 -28zM842 -560q0 -27 17 -52.5t52 -35.5q14 -3 26 -3q69 0 85 65l15 63q10 40 -9 72.5t-57 39.5q-34 11 -66.5 -7.5t-43.5 -54.5l-15 -63q-4 -18 -4 -24zM926 -250q0 -36 26 -62 t62 -26q38 0 63 25t25 63q0 37 -25 62t-63 25t-63 -25t-25 -62zM992 -8q-2 -24 14.5 -50t48.5 -32q37 -10 68 6t44 60l28 96q11 35 -7.5 67t-56.5 43q-35 11 -68 -8.5t-44 -56.5l-24 -96q-3 -14 -3 -29zM1287 -237q0 -27 16 -51.5t49 -34.5q5 0 15 -2t15 -2q65 0 81 70 l15 64q11 34 -7.5 67t-54.5 44q-39 10 -71.5 -8.5t-43.5 -56.5l-11 -63q0 -2 -1.5 -12t-1.5 -15zM1366 78q0 -37 26 -61q24 -26 62 -26t63 25t25 62q0 38 -25 63t-63 25t-63 -25t-25 -63zM1431 325q0 -27 17.5 -51.5t52.5 -34.5q3 0 12.5 -2t14.5 -2q17 0 39 10q33 17 43 56 l27 96q10 36 -8 67.5t-54 42.5q-37 11 -68.5 -6t-42.5 -54l-30 -97q0 -3 -1.5 -11.5t-1.5 -13.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M2 525q0 -179 104.5 -318.5t272.5 -190.5q14 -3 27 8l123 153q-142 0 -243 102t-101 246q0 135 90 234.5t224 110.5l56 7q18 0 18 14l8 59q20 176 148 291.5t303 115.5q176 0 307 -116.5t147 -290.5l8 -62q4 -18 23 -18h172q144 0 245 -101t101 -244q0 -133 -89.5 -232.5 t-220.5 -115.5q-20 0 -53 -6q-30 -3 -43 -24l-253 -298q-23 -29 -17.5 -67t33.5 -61q17 -20 61 -20q42 0 65 37l225 260q199 20 336 172t137 355q0 108 -41.5 206t-112 168.5t-168 112.5t-205.5 42h-34q-53 212 -226.5 347.5t-396.5 135.5q-149 0 -280.5 -63.5t-221.5 -177 t-121 -258.5q-180 -40 -293.5 -183.5t-113.5 -329.5zM363 -330q0 -10 6 -32q14 -34 47 -47q35 -16 71 -2t49 48q16 35 2 69t-49 46q-36 17 -69 3t-49 -50q-8 -17 -8 -35zM560 -70v-11q3 -36 32 -60q36 -20 66 -20q36 0 65 35l248 295q23 28 21 70q-4 34 -29.5 57t-55.5 23 q-8 0 -14 -1q-38 -8 -61 -35l-251 -296q-21 -24 -21 -57zM642 -573q0 -19 8 -34q13 -34 47 -50q17 -8 36 -8q20 0 33 8q36 14 49 44q16 35 2.5 71t-47.5 49q-35 16 -71.5 2t-48.5 -48q-8 -15 -8 -34zM821 -323v-12q4 -35 32.5 -58.5t58.5 -23.5q36 0 67 35l464 559 q19 22 19 55v13q-4 36 -29.5 57t-56.5 21h-14q-37 -2 -59 -33l-464 -555q-18 -26 -18 -58zM1195 -446q0 -14 6 -32q14 -35 49 -50q22 -6 33 -6q23 0 36 8q36 14 49 45q16 27 2 71q-13 33 -47 47l-37 10q-17 -3 -35 -8q-35 -13 -48 -47q-8 -19 -8 -38z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M2 527q0 184 115 327.5t291 184.5q50 218 225 358t400 140q220 0 392.5 -136.5t224.5 -350.5h35q143 0 265 -69.5t193 -190t71 -263.5q0 -105 -40 -201.5t-108 -167t-162.5 -114t-198.5 -46.5q-20 0 -20 18v142q0 19 20 19q136 7 232.5 109t96.5 241q0 140 -103.5 242 t-245.5 102h-173q-18 0 -18 18l-8 62q-18 173 -149 289.5t-304 116.5q-175 0 -304.5 -116.5t-145.5 -289.5l-8 -57q0 -20 -21 -20l-56 -3q-133 -16 -223.5 -114t-90.5 -230q0 -139 96 -241t233 -109q18 0 18 -19v-142q0 -18 -18 -18q-214 10 -362.5 163t-148.5 366z M574 -186q0 10 3 21l174 615q10 31 34.5 47t49.5 16q12 0 27 -3q38 -7 57 -39t8 -71l-174 -611q-20 -68 -88 -68q-5 0 -11 2q-9 3 -12 3q-34 10 -51 35.5t-17 52.5zM854 -486l259 936q7 31 32 47t53 16q13 0 28 -3q36 -10 53 -41.5t7 -68.5l-260 -937q-6 -27 -30.5 -46 t-53.5 -19q-16 0 -28 5q-32 8 -55 42q-17 27 -5 69zM1294 -189q0 11 3 24l174 615q9 31 32.5 47t49.5 16q14 0 29 -3q32 -9 48.5 -33t16.5 -50q0 -5 -2 -14.5t-2 -12.5l-173 -611q-6 -31 -30.5 -49.5t-54.5 -18.5l-26 5q-32 9 -48.5 34t-16.5 51z" />
|
||||
<glyph unicode="" horiz-adv-x="2228" d="M-1 525q0 185 115.5 329t296.5 185q47 220 221.5 361.5t400.5 141.5q223 0 396.5 -136t226.5 -352h35q108 0 206 -42t168 -112.5t111 -168.5t41 -206q0 -214 -146.5 -367t-359.5 -160q-20 0 -20 18v143q0 18 20 18q135 11 231 111.5t96 236.5q0 143 -102.5 246 t-244.5 103h-173q-19 0 -23 19l-8 61q-11 114 -74.5 206.5t-163.5 145t-216 52.5q-176 0 -305.5 -116.5t-146.5 -290.5l-7 -58q0 -15 -17 -15l-56 -8q-135 -11 -225.5 -110t-90.5 -235q0 -139 94.5 -239.5t231.5 -108.5q19 0 19 -18v-143q0 -18 -19 -18q-105 5 -200 48 t-163.5 113t-108.5 165.5t-40 200.5zM577 -197q0 5 2 14t2 12l29 110q11 36 42.5 54.5t68.5 7.5q36 -11 55 -42.5t8 -68.5l-26 -108q-21 -70 -81 -70q-4 0 -9.5 0.5t-12 1.5t-10.5 1q-34 10 -51 36.5t-17 51.5zM718 317q0 4 1.5 12t1.5 10l32 112q10 31 34 47.5t50 16.5 l27 -3q36 -11 54.5 -42.5t7.5 -68.5l-27 -107q-11 -44 -43 -62.5t-69 -2.5q-35 10 -52 36t-17 52zM849 -531q0 5 2 13.5t2 12.5l30 106q10 38 42.5 57.5t69.5 8.5q36 -11 54.5 -43.5t7.5 -69.5l-27 -111q-17 -65 -85 -65q-8 0 -26 4q-35 6 -52.5 32.5t-17.5 54.5zM992 -22 q0 14 3 27l30 110q11 36 43.5 54.5t69.5 7.5q36 -10 54 -41.5t6 -69.5l-27 -106q-20 -72 -76 -72q-7 0 -33 6q-35 7 -52.5 31.5t-17.5 52.5zM1293 -201q0 11 3 26l30 106q11 38 43.5 57.5t67.5 9.5q37 -11 56.5 -43.5t9.5 -67.5l-31 -113q-16 -65 -85 -65q-13 0 -27 3 q-32 6 -49 32.5t-18 54.5zM1440 307q0 5 5 28l32 110q6 34 31 50.5t52 14.5q7 1 26 -3q35 -8 55 -41q19 -27 8 -69l-26 -110q-21 -69 -81 -69q-10 0 -36 6q-33 10 -49.5 33.5t-16.5 49.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M-1 523q0 185 113.5 328.5t292.5 187.5q50 218 224.5 358t400.5 140q220 0 392.5 -136.5t224.5 -350.5h34q143 0 265 -70.5t193 -192t71 -264.5q0 -212 -148 -365t-360 -160q-21 0 -21 18v142q0 19 21 19q136 7 232.5 108.5t96.5 237.5q0 142 -103 245t-247 103h-172 q-19 0 -19 18l-8 62q-18 173 -148.5 290t-303.5 117q-176 0 -305.5 -118t-146.5 -293l-7 -53q0 -20 -20 -20l-56 -7q-133 -11 -223.5 -110.5t-90.5 -233.5q0 -136 96.5 -237.5t232.5 -108.5q18 0 18 -19v-142q0 -18 -18 -18q-214 7 -362.5 160t-148.5 365zM678 89 q0 36 25.5 62t62.5 26t62.5 -26t25.5 -62q0 -38 -25.5 -64.5t-62.5 -26.5t-62.5 26.5t-25.5 64.5zM678 -298q0 38 26 64q26 24 62 24q38 0 63 -25t25 -63t-25 -63t-63 -25t-63 25t-25 63zM1018 -117q0 37 27 66q26 26 61 26q38 0 65 -27.5t27 -64.5t-27 -63.5t-65 -26.5 q-36 0 -62 26.5t-26 63.5zM1018 269q0 37 27 64q28 26 61 26q38 0 65 -26.5t27 -63.5t-27 -62.5t-65 -25.5q-36 0 -62 25.5t-26 62.5zM1018 -507q0 36 27 65q26 26 61 26q38 0 65 -27t27 -64t-27 -62.5t-65 -25.5q-36 0 -62 25.5t-26 62.5zM1362 89q0 35 27 61.5t64 26.5 t62.5 -26t25.5 -62q0 -38 -25.5 -64.5t-62.5 -26.5t-64 27t-27 64zM1362 -298q0 35 27 64q25 24 64 24q37 0 62.5 -25t25.5 -63t-25.5 -63t-62.5 -25q-38 0 -64.5 25.5t-26.5 62.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2211" d="M-1 527q0 184 115 327.5t291 184.5q49 218 224 357.5t401 139.5q220 0 392 -136t225 -350h33q143 0 265 -69.5t193 -190t71 -263.5q0 -214 -147.5 -368t-360.5 -161q-21 0 -21 18v142q0 19 21 19q137 7 233 109t96 241t-104 241.5t-246 102.5h-171q-20 0 -20 18l-7 62 q-17 172 -147.5 289t-304.5 117q-175 0 -305 -116.5t-147 -289.5l-7 -58q0 -19 -20 -19l-56 -3q-131 -6 -222.5 -107t-91.5 -237q0 -139 96 -241t233 -109q18 0 18 -19v-142q0 -18 -18 -18q-214 10 -362.5 163t-148.5 366zM631 433q0 39 39 105.5t73 107.5q34 38 41 45 l38 -43q41 -44 76.5 -108.5t35.5 -106.5q0 -63 -43 -105t-107 -42q-63 0 -108 43t-45 104zM949 8q0 44 25.5 102t62.5 109q29 41 71 90t63 69q22 20 27 25l26 -25q60 -53 136 -156q38 -53 63 -111t25 -103q0 -103 -72.5 -175.5t-177.5 -72.5q-103 0 -176 72t-73 176z M1106 718q0 67 104 171l25 -27q75 -92 75 -144q0 -41 -29.5 -70.5t-70.5 -29.5q-43 0 -73.5 29.5t-30.5 70.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2211" d="M1 527q0 -177 106 -317t274 -191l-70 -179q-5 -23 15 -23h227l-111 -403h30l423 557q6 7 2 14.5t-15 7.5h-232l264 495q10 22 -15 22h-314q-15 0 -24 -15l-115 -306q-114 29 -188.5 124t-74.5 214q0 133 90 230.5t224 113.5l56 8q21 0 21 18l8 55q16 173 145.5 290 t304.5 117q174 0 304.5 -117t149.5 -290l7 -62q0 -19 19 -19h173q145 0 247 -100.5t102 -243.5q0 -136 -95 -235.5t-234 -109.5q-20 0 -20 -20v-146q0 -18 20 -18q104 3 198.5 47t162.5 114.5t108 167t40 200.5q0 144 -71 265.5t-193 192t-265 70.5h-35q-53 213 -225 348 t-393 135q-226 0 -401 -140t-224 -358q-176 -41 -291 -184.5t-115 -328.5zM871 -525q0 -25 16.5 -49.5t49.5 -34.5q22 -5 28 -5q14 0 40 11q33 15 44 56l30 112q10 35 -8.5 67t-56.5 43q-35 10 -67.5 -8.5t-43.5 -56.5l-29 -107q-3 -27 -3 -28zM1014 -16q0 -23 16.5 -46.5 t48.5 -35.5q36 -12 68 5t43 56l32 111q10 35 -8.5 67.5t-56.5 43.5q-36 10 -69.5 -8.5t-44.5 -55.5l-26 -108q-3 -27 -3 -29zM1315 -192q0 -27 17.5 -54t50.5 -37q4 0 12.5 -2t12.5 -2q21 0 40 8q31 12 45 61l26 108q11 37 -6.5 70.5t-53.5 44.5q-40 10 -72.5 -9t-39.5 -57 l-29 -110q-3 -9 -3 -21zM1461 319q-1 -25 15.5 -50t51.5 -40q12 -6 29 -6q15 0 35 9q33 16 47 61l31 110q3 21 3 23q0 27 -17.5 52.5t-52.5 35.5q-4 0 -12 2t-12 2q-27 0 -51.5 -16.5t-34.5 -51.5l-30 -108q-2 -8 -2 -23z" />
|
||||
<glyph unicode="" horiz-adv-x="2211" d="M2 527q0 -177 106 -317t275 -191l-70 -179q-5 -23 15 -23h227l-105 -459h30l418 613q6 7 2 14.5t-15 7.5h-232l264 495q11 23 -15 23h-315q-15 0 -25 -16l-114 -306q-114 29 -189 124t-75 214q0 133 90.5 231t224.5 114l56 7q21 0 21 19l7 54q17 173 146.5 290t304.5 117 q174 0 304.5 -117t149.5 -290l7 -62q0 -18 19 -18h172q145 0 248 -101.5t103 -243.5q0 -136 -95.5 -235.5t-235.5 -110.5q-20 0 -20 -19v-146q0 -18 20 -18q213 7 361.5 161t148.5 368q0 144 -71 265.5t-193 192t-266 70.5h-33q-53 212 -226 347.5t-393 135.5 q-226 0 -401 -140t-224 -358q-177 -41 -292 -184.5t-115 -328.5zM871 -509q0 -63 63 -82q3 0 12 -1.5t14 -1.5q27 0 52.5 15.5t34.5 51.5l240 927q10 38 -7 69t-53 42q-27 3 -28 3q-26 0 -50.5 -16t-33.5 -48l-241 -930q-3 -13 -3 -29zM1314 -182q0 -19 12 -40 q22 -35 53 -47q17 -5 32 -5q16 0 35 8q32 14 44 61l155 605q4 18 4 29q0 24 -17 48t-49 34q-27 3 -28 3q-27 0 -50 -15.5t-32 -48.5l-155 -608q0 -4 -2 -12t-2 -12z" />
|
||||
<glyph unicode="" horiz-adv-x="2211" d="M2 678q0 36 25 60t61 24h1289q35 0 58 -23.5t23 -60.5q0 -35 -23 -58t-58 -23h-1289q-36 0 -61 23t-25 58zM261 987q0 35 25 59q24 24 59 24h1290q34 0 58 -24t24 -59t-24 -59.5t-58 -24.5h-1290q-35 0 -59.5 24.5t-24.5 59.5zM432 375q0 34 26 58q23 23 59 23h1290 q36 0 60 -23t24 -58t-24.5 -60t-59.5 -25h-1290q-35 0 -60 25t-25 60zM1561 678q0 37 24 60.5t61 23.5h481q37 0 60.5 -24t23.5 -60q0 -35 -24 -58t-60 -23h-481q-37 0 -61 23t-24 58z" />
|
||||
<glyph unicode="" d="M-10 89q0 -38 28 -64q27 -27 65 -27h613q42 0 73.5 -30.5t31.5 -72.5q0 -43 -31.5 -74t-73.5 -31q-41 0 -73 32q-29 26 -65 26q-38 0 -64.5 -26.5t-26.5 -63.5q0 -35 27 -64q84 -84 202 -84t201.5 83t83.5 202q0 118 -83.5 202t-201.5 84h-613q-38 0 -65.5 -27.5 t-27.5 -64.5zM-10 411q0 -36 28 -62t65 -26h1158q118 0 201.5 83t83.5 201t-83.5 200.5t-201.5 82.5q-122 0 -202 -81q-24 -25 -24 -65t24.5 -64t62.5 -24t66 24q30 30 73 30q41 0 72 -30t31 -73q0 -42 -31 -73t-72 -31h-1158q-38 0 -65.5 -27.5t-27.5 -64.5zM258 662 q0 -14 17 -14h154q12 0 22 16q36 87 111.5 143.5t168.5 63.5l56 8q21 0 21 18l8 55q17 173 146.5 289.5t304.5 116.5t305 -116t148 -290l7 -62q0 -19 19 -19h174q145 0 247 -101t102 -243t-102.5 -244t-246.5 -102h-737q-18 0 -18 -19v-146q0 -18 18 -18h737q143 0 264.5 71 t192.5 193t71 265q0 141 -73 264q117 113 161 275l16 72q2 2 2 8q0 7 -15 17l-64 22q-91 28 -155 89.5t-91.5 131t-27.5 139.5q0 43 9 84l15 66q4 15 -15 24l-84 26q-70 17 -133 17q-59 0 -120 -14t-126 -43.5t-126.5 -85t-106.5 -130.5q-113 48 -247 48q-226 0 -399 -140 t-220 -357q-137 -32 -242 -131t-145 -235v-3q-3 -5 -3 -9zM1670 1397q50 88 138 134.5t182 46.5q22 0 33 -1q-2 -14 -2 -38q0 -151 84 -289t232 -207q-25 -60 -80 -110q-142 122 -337 122h-35q-43 201 -215 342z" />
|
||||
<glyph unicode="" d="M-146 86q0 -38 26.5 -63t66.5 -25h1004q38 0 63 25t25 63q0 40 -25 65.5t-63 25.5h-1004q-40 0 -66.5 -25.5t-26.5 -65.5zM135 411q0 -39 27 -64q25 -27 64 -27h1006q37 0 62.5 26.5t25.5 64.5q0 37 -25 62.5t-63 25.5h-1006q-38 0 -64.5 -25.5t-26.5 -62.5zM246 661 q0 -15 19 -15h152q14 0 24 15q36 87 111 144t168 64l58 8q20 0 20 18l7 55q17 174 147 290.5t306 116.5q175 0 303.5 -115t150.5 -289l8 -62q0 -18 18 -18h173q145 0 246.5 -102t101.5 -246q0 -141 -103 -244.5t-245 -103.5h-737q-19 0 -19 -18v-143q0 -18 19 -18h737 q144 0 266 70t193 191.5t71 265.5q0 142 -70 264q117 104 162 275l19 73q1 2 1 7q0 13 -16 17l-66 23q-70 21 -124 61t-85.5 89.5t-47 100.5t-15.5 101q0 43 11 93l15 65q7 15 -15 24l-88 26q-70 17 -132 17q-60 0 -121 -14t-126 -43.5t-125.5 -85t-105.5 -130.5 q-124 51 -254 51q-226 0 -400 -140.5t-221 -360.5q-139 -32 -243.5 -130.5t-145.5 -235.5v-3q-2 -2 -2 -8zM322 -245q0 -38 28 -64q26 -27 64 -27h1005q38 0 65.5 27t27.5 64t-27.5 62.5t-65.5 25.5h-1005q-38 0 -65 -25.5t-27 -62.5zM1665 1394q55 88 143.5 136.5 t181.5 46.5q18 0 27 -1v-26q0 -156 84.5 -297.5t231.5 -211.5q-27 -62 -82 -114q-141 126 -340 126h-34q-40 193 -212 341z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-1 527q0 -213 148.5 -366t362.5 -163q19 0 19 18v143q0 18 -19 18q-137 7 -233 109t-96 241q0 133 90 231t224 114l56 3q20 0 20 19l8 58q17 173 147 290t305 117q173 0 303.5 -117t148.5 -290l8 -62q0 -18 19 -18h172q142 0 246 -102.5t104 -242.5q0 -139 -96 -241 t-233 -109q-21 0 -21 -18v-143q0 -18 21 -18q213 7 360.5 161t147.5 368q0 138 -68 257q125 117 164 279l15 73q3 2 3 7q0 12 -18 17l-59 18q-91 27 -155.5 90.5t-91.5 133t-27 140.5q-1 39 8 84l15 62q5 14 -15 23l-85 27q-67 20 -140 20q-56 0 -116 -13.5t-124.5 -43 t-126.5 -85t-107 -130.5q-120 52 -252 52q-226 0 -401 -140t-224 -358q-177 -41 -292 -184.5t-115 -328.5zM583 -223q14 -34 49 -48q31 -16 66 -2.5t48 47.5q16 35 2.5 69t-47.5 47q-32 16 -66 2t-50 -49q-16 -25 -2 -66zM650 79q0 -24 16.5 -48t48.5 -34q41 -16 72 0.5 t43 60.5l93 342q11 40 -8 71.5t-57 39.5q-35 11 -67.5 -7t-43.5 -54l-93 -343q0 -3 -2 -13t-2 -15zM849 -518q0 -20 6 -31q14 -35 48 -48q15 -8 35 -8q10 0 32 6q36 13 51.5 48t-0.5 70t-48 49t-66 0q-31 -13 -44.5 -38t-13.5 -48zM928 -235q0 -61 67 -83q15 -5 26 -5 q17 0 37 9q35 13 49 61l176 653q10 38 -7 69t-53 42q-37 11 -69.5 -7t-42.5 -54l-180 -658q-3 -14 -3 -27zM1295 -191q0 -20 7 -33q13 -32 47 -47q19 -8 37 -8q10 0 32 6q35 14 48 47q13 35 0.5 67.5t-44.5 48.5q-35 16 -69.5 2.5t-50.5 -49.5q-7 -13 -7 -34zM1371 82 q0 -25 17 -48.5t49 -33.5q27 -3 29 -3q64 0 81 65l94 338q10 38 -8 69t-54 42q-37 11 -68 -6.5t-42 -54.5l-94 -339q-4 -18 -4 -29zM1441 1389q50 92 138.5 140t187.5 47q18 0 27 -2v-33q0 -156 83.5 -293.5t231.5 -207.5q-31 -70 -80 -114q-141 125 -347 125h-34 q-41 200 -207 338z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-1 527q0 -213 148.5 -366t362.5 -163q18 0 18 18v146q0 19 -18 19q-139 11 -234 110.5t-95 235.5q0 134 90.5 233.5t223.5 110.5l56 8q20 0 20 18l8 55q17 173 146.5 289.5t304.5 116.5q174 0 304 -116t148 -290l8 -62q0 -19 19 -19h172q145 0 247.5 -101t102.5 -243 q0 -136 -95 -235.5t-234 -110.5q-21 0 -21 -19v-146q0 -18 21 -18q213 7 360.5 161t147.5 368q0 143 -73 264q128 116 165 275l16 77q1 1 1 7q0 12 -17 17l-62 18q-91 26 -155 88t-91 131.5t-27 140.5q0 39 10 84l15 66q4 15 -15 24l-84 26q-70 17 -133 17q-58 0 -119 -14 t-127 -43.5t-128 -85t-107 -130.5q-113 48 -249 48q-226 0 -400.5 -139.5t-224.5 -357.5q-176 -42 -291 -185.5t-115 -327.5zM817 31q-8 -23 15 -23h230l-140 -442h32l445 596q6 7 2.5 14.5t-14.5 7.5h-234l246 449q11 23 -15 23h-314q-13 0 -23 -15zM1435 1391 q53 91 141.5 139t184.5 48q20 0 29 -2v-33q0 -154 83 -291t231 -209q-25 -59 -80 -114q-147 126 -343 126h-34q-45 199 -212 336z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-5 525q0 -212 149 -366t363 -161q20 0 20 18v143q0 18 -20 18q-136 7 -233 110t-97 238q0 136 91 235.5t225 110.5l57 7q20 0 20 19l7 54q17 176 147 293.5t306 117.5q174 0 305.5 -117t149.5 -290l8 -61q0 -20 18 -20h172q145 0 248.5 -103t103.5 -246 q0 -88 -44 -166.5t-120.5 -127.5t-166.5 -54q-21 0 -21 -18v-143q0 -18 21 -18q105 3 200 46.5t163 114t108 166.5t40 200q0 141 -73 268q133 119 169 280l15 73q2 2 2 8q0 9 -17 17l-60 19q-70 21 -124.5 62.5t-86.5 92.5t-48.5 103.5t-16.5 102.5q-3 38 9 88l15 62 q7 16 -15 25l-85 26q-65 18 -138 18q-58 0 -119.5 -14t-127 -44t-127.5 -86.5t-107 -131.5q-130 49 -250 49q-226 0 -402 -140.5t-226 -359.5q-180 -46 -293.5 -189t-113.5 -329zM573 -227q0 -27 17 -54t50 -37q37 -11 68.5 4t42.5 60l15 65q8 36 -10 67.5t-55 42.5 q-36 11 -68.5 -8t-42.5 -57l-15 -63q-2 -6 -2 -20zM654 82q0 -35 26 -61q25 -27 61 -27q38 0 64 25.5t26 62.5t-26 62.5t-64 25.5q-37 0 -62 -25t-25 -63zM719 325q-2 -25 14 -48.5t51 -34.5q33 -10 66.5 7.5t44.5 54.5l30 96q12 39 -7.5 69.5t-58.5 41.5q-35 11 -67 -7 t-43 -53l-27 -98q-3 -27 -3 -28zM842 -560q0 -27 17 -52.5t52 -35.5q14 -3 26 -3q69 0 85 65l15 63q10 40 -9 72.5t-57 39.5q-34 11 -66.5 -7.5t-43.5 -54.5l-15 -63q-4 -18 -4 -24zM926 -250q0 -36 26 -62t62 -26q38 0 63 25t25 63q0 37 -25 62t-63 25t-63 -25t-25 -62z M992 -8q-2 -24 14.5 -50t48.5 -32q37 -10 68 6t44 60l28 96q11 35 -7.5 67t-56.5 43q-35 11 -68 -8.5t-44 -56.5l-24 -96q-3 -14 -3 -29zM1287 -237q0 -27 16 -51.5t49 -34.5q5 0 15 -2t15 -2q65 0 81 70l15 64q11 34 -7.5 67t-54.5 44q-39 10 -71.5 -8.5t-43.5 -56.5 l-11 -63q0 -2 -1.5 -12t-1.5 -15zM1366 78q0 -37 26 -61q24 -26 62 -26t63 25t25 62q0 38 -25 63t-63 25t-63 -25t-25 -63zM1431 325q0 -27 17.5 -51.5t52.5 -34.5q3 0 12.5 -2t14.5 -2q17 0 39 10q33 17 43 56l27 96q10 36 -8 67.5t-54 42.5q-37 11 -68.5 -6t-42.5 -54 l-30 -97q0 -3 -1.5 -11.5t-1.5 -13.5zM1438 1397q51 93 139.5 143t183.5 49q15 0 32 -3v-34q-2 -157 82.5 -294.5t236.5 -206.5q-32 -64 -85 -118q-148 122 -344 122h-33q-50 209 -212 342z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-1 525q0 -179 106 -320.5t274 -188.5q14 -3 27 8l120 150q-140 0 -242.5 104t-102.5 247q0 134 90 231.5t225 109.5l53 7q20 0 20 20l8 57q20 174 150 291t305 117q174 0 305 -117.5t150 -290.5l7 -62q0 -18 19 -18h173q142 0 244 -102t102 -243q0 -136 -90 -236.5 t-221 -111.5q-72 -9 -92 -30l-250 -310q-24 -27 -19 -67q4 -38 33.5 -63t60.5 -25q36 0 68 40l217 276q99 10 187.5 56t152 115.5t100.5 162.5t37 193q0 139 -73 260q130 118 169 280v10l21 82l-82 28q-92 27 -156 89t-91.5 131t-27.5 140q0 41 9 85l20 83l-90 25q-1 1 -3 2 t-3 2q-2 1 -4.5 2t-3.5 1q-70 17 -133 17q-61 -1 -122.5 -15t-128 -44t-128.5 -86t-107 -132q-120 52 -250 52q-226 0 -401 -140t-225 -358q-181 -44 -294 -186.5t-113 -327.5zM394 -327q0 -21 7 -33q14 -35 46 -49q35 -16 71 -3t49 47q16 35 1.5 71.5t-48.5 48.5 q-35 16 -70.5 2.5t-48.5 -48.5q-7 -15 -7 -36zM591 -66v-12q3 -36 35 -59q21 -24 58 -23t70 34l248 311q22 28 17.5 66.5t-32.5 61.5t-67 19t-61 -36l-248 -305q-20 -23 -20 -57zM651 -622q14 -34 50 -48q17 -8 35 -8q10 0 32 6q34 14 47 47q13 35 1 69t-47 51 q-35 13 -67 -0.5t-48 -46.5q-18 -31 -3 -70zM822 -338v-9q4 -36 33.5 -61.5t59.5 -25.5q35 0 64 36l461 572q23 27 20 66t-31 62q-32 23 -70.5 19.5t-60.5 -31.5l-456 -572q-20 -25 -20 -56zM1195 -456q0 -18 8 -35q13 -36 51 -50q36 -14 65 -2q35 14 49 49q16 35 3 68 t-48 50q-35 13 -69.5 0t-50.5 -45q-8 -19 -8 -35zM1440 1391q50 92 138.5 140.5t187.5 46.5q19 0 28 -1v-32q0 -155 85.5 -293.5t233.5 -209.5q-40 -75 -84 -119q-142 126 -343 126h-35q-49 206 -211 342z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-1 528q0 -213 149 -366.5t363 -163.5q19 0 19 18v143q0 18 -19 18q-137 8 -233.5 110t-96.5 241q0 133 90.5 231.5t224.5 114.5l57 4q21 0 21 18l7 58q17 173 147 290.5t305 117.5q174 0 305 -117.5t149 -290.5l8 -61q0 -19 18 -19h173q143 0 247.5 -102.5t104.5 -243.5 q0 -138 -97 -240.5t-234 -110.5q-21 0 -21 -18v-143q0 -18 21 -18q213 7 361.5 161.5t148.5 368.5q0 141 -73 262q129 117 169 279l15 77q2 1 2 7q0 12 -17 17l-60 19q-91 26 -156 88.5t-92.5 131.5t-27.5 137q-3 36 9 88l15 65q7 16 -15 26l-84 26q-72 16 -135 16 q-60 0 -122 -14t-128 -43.5t-128 -85t-107 -130.5q-132 48 -249 48q-226 0 -401.5 -140.5t-225.5 -359.5q-177 -41 -292 -185t-115 -329zM592 -201q0 -27 17.5 -52.5t52.5 -35.5q37 -11 68.5 4.5t42.5 59.5l153 626q10 40 -9 72t-56 39q-35 11 -67.5 -7t-43.5 -54l-155 -629 q-3 -21 -3 -23zM870 -529q0 -25 16.5 -49t47.5 -33q18 -4 26 -4q70 0 87 63l240 953q10 39 -7.5 69.5t-53.5 41.5q-37 11 -70.5 -7.5t-41.5 -53.5l-241 -952q0 -2 -1.5 -12.5t-1.5 -15.5zM1314 -210q0 -57 67 -79q22 -6 32 -6q18 0 37 8q32 13 41 62l154 626q10 38 -8 69 t-54 42q-37 11 -70 -7t-41 -54l-153 -629q-5 -27 -5 -32zM1440 1395q51 93 139.5 141.5t187.5 46.5q18 0 28 -1v-32q-2 -155 82.5 -293t236.5 -210q-36 -73 -84 -114q-147 121 -344 121h-33q-44 203 -213 341z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-1 527q0 -213 148.5 -366t362.5 -163q18 0 18 18v146q0 19 -18 19q-139 11 -234 110.5t-95 235.5q0 132 90 230t224 114l56 8q20 0 20 18l8 55q17 173 146.5 289.5t304.5 116.5q174 0 304 -116t148 -290l8 -62q0 -19 19 -19h172q144 0 247 -101t103 -243 q0 -136 -95 -235.5t-234 -110.5q-21 0 -21 -19v-146q0 -18 21 -18q213 7 360.5 161t147.5 368q0 139 -69 259q130 117 169 279v14l20 84l-81 22q-130 39 -202 144.5t-72 216.5q0 42 9 83l21 85l-91 27l-15 4q-75 15 -132 15q-60 0 -122 -14t-128.5 -44t-128 -85.5 t-106.5 -131.5q-119 52 -252 52q-226 0 -399.5 -140t-220.5 -358q-180 -41 -295.5 -184t-115.5 -328zM575 -195q0 -24 16 -47.5t48 -35.5q35 -12 68 5.5t44 54.5l30 113q11 33 -7.5 66t-54.5 44q-37 10 -69.5 -9t-44.5 -57l-26 -106q-4 -20 -4 -28zM713 310q0 -20 10 -38 q12 -27 58 -41q39 -10 70 6.5t43 55.5l29 110q11 37 -7 68.5t-54 41.5q-39 10 -71.5 -7.5t-43.5 -55.5l-28 -108q-6 -22 -6 -32zM847 -528q0 -27 16.5 -52.5t48.5 -35.5q18 -5 24 -5q14 0 40 11q32 13 46 59l32 112q11 34 -7.5 67t-54.5 44q-39 10 -71.5 -8.5t-43.5 -56.5 l-27 -108q-3 -13 -3 -27zM989 -19q0 -24 16 -47.5t49 -35.5q36 -11 68 6t43 56l29 111q11 34 -6.5 66.5t-52.5 43.5q-39 10 -72.5 -9t-44.5 -57l-26 -107q0 -3 -1 -8.5t-1.5 -10t-0.5 -8.5zM1288 -207q0 -61 67 -80q13 -3 27 -3q24 0 39 7q32 13 46 61l30 109 q10 40 -8.5 71.5t-56.5 39.5q-37 11 -68.5 -7.5t-42.5 -54.5l-30 -111q0 -4 -1 -10.5t-1.5 -12t-0.5 -9.5zM1435 307q0 -25 17 -49t50 -34q23 -5 25 -5q14 0 40 11q33 13 47 59l29 111q10 35 -9 67t-56 43q-35 11 -67.5 -7.5t-43.5 -55.5l-27 -113q-5 -23 -5 -27zM1440 1391 q51 90 141.5 140t193.5 50h22q-2 -28 -2 -40q0 -152 84 -289t232 -209q-34 -67 -84 -117q-149 129 -346 129h-34q-40 189 -207 336z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-1 525q0 -212 149 -366t363 -161q19 0 19 18v143q0 18 -19 18q-136 7 -233 109.5t-97 238.5t90.5 235t224.5 110l57 8q21 0 21 18l7 55q17 175 146.5 293t305.5 118q174 0 305 -117.5t149 -290.5l8 -61q0 -19 18 -19h173q145 0 248.5 -103t103.5 -246 q0 -136 -97.5 -238.5t-233.5 -109.5q-21 0 -21 -18v-143q0 -18 21 -18q140 4 257.5 76t185 192t67.5 259q0 144 -70 265q119 107 163 275l18 77q2 2 2 8q0 12 -17 17l-65 18q-70 21 -124.5 61t-86 89.5t-47 101t-15.5 101.5q0 43 11 92l12 66q4 15 -15 24l-85 26 q-70 17 -133 17q-59 0 -120 -14t-126 -44t-126 -85.5t-106 -130.5q-129 53 -254 53q-226 0 -401.5 -140.5t-225.5 -359.5q-180 -45 -293.5 -188t-113.5 -329zM680 89q0 -38 25.5 -64.5t62.5 -26.5q38 0 63.5 26.5t25.5 64.5q0 36 -25.5 62t-63.5 26q-37 0 -62.5 -26 t-25.5 -62zM680 -299q0 -36 26 -62t62 -26q38 0 63.5 25t25.5 63t-25.5 63t-63.5 25t-63 -25t-25 -63zM1022 -118q0 -39 26 -63q26 -26 62 -26q38 0 65 26t27 63q0 38 -27 65.5t-65 27.5q-35 0 -61.5 -27.5t-26.5 -65.5zM1022 270q0 -38 26 -62q26 -26 62 -26q39 0 65.5 25 t26.5 63q0 37 -27 63.5t-65 26.5q-36 0 -62 -26.5t-26 -63.5zM1022 -510q0 -35 26 -61q27 -27 62 -27q38 0 65 25.5t27 62.5q0 38 -27 65.5t-65 27.5q-35 0 -61.5 -27.5t-26.5 -65.5zM1367 89q0 -38 26.5 -64.5t63.5 -26.5t62.5 26.5t25.5 64.5q0 36 -25.5 62t-62.5 26 t-63.5 -26t-26.5 -62zM1367 -299q0 -36 26 -62t64 -26q37 0 62.5 25.5t25.5 62.5q0 38 -25 63t-63 25t-64 -25t-26 -63zM1440 1395q50 87 138.5 134.5t182.5 49.5q23 0 34 -2v-33q0 -155 83.5 -292.5t232.5 -209.5q-25 -58 -81 -114q-142 126 -344 126h-33q-44 197 -213 341 z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M2 529q0 -213 148.5 -366t362.5 -164q20 0 20 19v142q0 19 -20 19q-137 7 -233 109t-96 241q0 133 90 231t224 114l56 4q21 0 21 19l8 58q17 173 146.5 289.5t304.5 116.5q174 0 305 -117t149 -289l7 -61q0 -20 19 -20h173q142 0 246 -102.5t104 -242.5 q0 -139 -96.5 -241t-233.5 -109q-20 0 -20 -19v-142q0 -19 20 -19q140 5 257.5 77t185 192.5t67.5 260.5q0 139 -73 261q126 120 165 275l14 78q3 1 3 7q0 12 -17 17l-62 18q-91 26 -156 87.5t-92.5 129.5t-27.5 137q0 46 12 91l15 65q4 16 -15 25l-85 26q-72 16 -135 16 q-58 0 -119 -14t-126.5 -43t-127.5 -84t-107 -128q-130 49 -249 49q-226 0 -401 -140.5t-225 -358.5q-177 -42 -291.5 -185.5t-114.5 -328.5zM635 435q0 -61 45 -104t109 -43t106.5 42.5t42.5 104.5q0 41 -37 109t-69 105q-25 28 -43 46l-38 -44q-43 -47 -79.5 -110.5 t-36.5 -105.5zM954 10q0 -105 73 -177t176 -72q105 0 178 73t73 176q0 87 -86 213q-71 93 -137 159q-13 9 -28 24l-25 -24q-63 -58 -136 -158q-38 -53 -63 -111t-25 -103zM1111 721q0 -41 30.5 -70t74.5 -29q41 0 70 29t29 70q0 68 -99 173l-26 -29q-30 -32 -54.5 -74.5 t-24.5 -69.5zM1438 1395q56 91 142.5 137.5t182.5 46.5q19 0 29 -2v-32q0 -154 84.5 -291.5t233.5 -210.5q-25 -60 -80 -110q-148 122 -343 122h-34q-49 210 -215 340z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M1 529q0 -177 106 -316.5t275 -190.5l-69 -181q-7 -22 15 -22h226l-138 -446h30l451 600q6 7 2.5 14.5t-14.5 7.5h-232l264 495q11 23 -15 23h-316q-14 0 -24 -16l-114 -307q-114 29 -189.5 124.5t-75.5 214.5q0 133 90.5 231t224.5 114l56 8q21 0 21 19l8 54 q17 173 146.5 290t304.5 117q174 0 305 -117.5t149 -289.5l8 -61q0 -20 18 -20h173q145 0 248 -101.5t103 -243.5q0 -136 -96 -236t-235 -110q-20 0 -20 -20v-145q0 -19 20 -19q213 7 361.5 161.5t148.5 368.5q0 139 -70 261q124 119 162 280l19 73q1 1 1 7q0 13 -16 17 l-66 18q-92 27 -156 89.5t-90.5 130t-25.5 134.5q0 44 11 91l12 65q4 16 -15 25l-85 26q-75 15 -132 15q-59 1 -120.5 -12.5t-126.5 -43t-125.5 -84t-105.5 -128.5q-136 49 -254 49q-226 0 -401 -140.5t-225 -358.5q-177 -42 -292 -185.5t-115 -328.5zM873 -523 q0 -25 16.5 -50t48.5 -35q25 -5 29 -5q15 0 39 11q33 16 45 56l30 112q10 35 -8.5 67.5t-56.5 43.5q-35 10 -67.5 -9t-43.5 -57l-28 -107q0 -3 -2 -12.5t-2 -14.5zM1016 -16q0 -69 65 -80q23 -5 29 -5q60 0 82 67l32 109q10 35 -9 67.5t-57 43.5q-36 11 -68.5 -7.5 t-43.5 -56.5l-27 -108q-3 -14 -3 -30zM1315 -194q2 -27 19 -51.5t51 -36.5q26 -6 36 -6q54 0 75 72l26 109q11 37 -6.5 70t-53.5 44q-40 10 -72.5 -9t-39.5 -57l-31 -110q0 -4 -2 -12.5t-2 -12.5zM1441 1395q53 89 143 137.5t189 48.5h22v-34q0 -102 36 -198t108.5 -177 t171.5 -129q-27 -60 -81 -110q-146 125 -343 125h-34q-45 200 -212 337zM1462 318q0 -69 69 -88q22 -4 32 -4q58 0 79 69l30 111q1 8 1 23q2 27 -15 52.5t-52 35.5q-2 0 -10.5 1.5t-13.5 1.5q-26 0 -51 -16.5t-35 -50.5l-31 -109q0 -1 -1.5 -11t-1.5 -15z" />
|
||||
<glyph unicode="" horiz-adv-x="2331" d="M-3 531q0 -178 105.5 -317.5t274.5 -190.5l-70 -180q-4 -22 16 -22h227l-104 -374h31l417 527q6 8 1.5 15.5t-15.5 7.5h-232l264 494q12 23 -15 23h-315q-14 0 -24 -15l-115 -307q-115 29 -190 124.5t-75 214.5q0 133 91 231.5t225 114.5l56 8q20 0 20 18l8 55 q17 173 147 290t305 117q173 0 304.5 -117.5t150.5 -289.5l6 -63q0 -18 20 -18h172q145 0 248 -101.5t103 -244.5q0 -136 -95.5 -236t-234.5 -111q-21 0 -21 -18v-147q0 -19 21 -19q140 5 257.5 77t185 192.5t67.5 261.5q0 139 -70 261q127 121 166 280l15 77q2 2 2 8 q0 11 -17 16l-61 19q-134 38 -204.5 142.5t-70.5 217.5q0 42 9 85l15 65q7 16 -15 25q-34 14 -97 28t-123 14q-58 0 -119 -14t-126.5 -43.5t-127.5 -85t-107 -130.5q-132 48 -253 48q-226 0 -401.5 -140t-225.5 -358q-177 -41 -291.5 -185.5t-114.5 -329.5zM861 -517 q0 -26 15 -49.5t47 -32.5q17 -3 32 -3q66 0 82 67l246 938q10 38 -7 69.5t-53 41.5q-37 11 -69.5 -6.5t-42.5 -52.5l-247 -943q-3 -14 -3 -29zM1305 -195q0 -26 15.5 -49t49.5 -33q5 0 17 -1.5t18 -1.5q60 0 76 67l160 616q10 39 -8 70t-54 41q-37 11 -68.5 -6t-41.5 -53 l-160 -621q-4 -22 -4 -29zM1438 1398q53 91 141.5 139t187.5 48q19 0 28 -1v-34q0 -154 84 -291t232 -210q-29 -65 -85 -114q-147 126 -343 126h-34q-45 200 -211 337z" />
|
||||
<glyph unicode="" horiz-adv-x="1600" d="M15 786q0 153 60 293t161 241.5t241.5 162t293.5 60.5h123q25 -7 25 -30l4 -94q6 -203 146.5 -346t340.5 -151l88 -7q25 0 25 -25v-104q1 -205 -99.5 -379.5t-274 -276t-378.5 -101.5q-156 0 -296 60t-241 161.5t-160 241.5t-59 294zM210 786q0 -162 82 -294.5 t210 -203.5t269 -71q93 0 187.5 36.5t176 102t140 167.5t75.5 223q-261 54 -418.5 223.5t-181.5 398.5q-151 -8 -276.5 -93t-194.5 -215.5t-69 -273.5z" />
|
||||
<glyph unicode="" d="M-3 93q0 -39 28 -64q29 -29 65 -29h628q42 0 73.5 -30t31.5 -73q0 -41 -32 -72.5t-73 -31.5q-40 0 -72 32q-30 28 -67 28t-63 -27t-26 -65q0 -37 27 -64q83 -83 201 -83t201 82.5t83 200.5q0 119 -83 203t-201 84h-628q-38 0 -65.5 -27t-27.5 -64zM-3 414q0 -37 28 -62 q24 -26 65 -26h1173q118 0 201 83t83 201t-83 200.5t-201 82.5q-122 0 -202 -80q-24 -27 -24 -67q0 -38 24.5 -62.5t63.5 -24.5q40 0 65 24q30 30 73 30q41 0 72 -30t31 -73t-31 -74t-72 -31h-1173q-38 0 -65.5 -27t-27.5 -64zM280 664q0 -13 17 -13h153q13 0 23 15 q36 87 111.5 144t169.5 64l56 7q21 0 21 20l7 53q17 173 146.5 289.5t304.5 116.5t304.5 -115.5t148.5 -290.5l7 -61q0 -19 19 -19h174q144 0 245.5 -101t101.5 -243q0 -143 -101.5 -244.5t-245.5 -101.5h-737q-19 0 -19 -19v-146q0 -19 19 -19h737q143 0 264.5 71t192 193 t70.5 266q0 118 -45 216q121 159 121 355q0 114 -44.5 217.5t-119.5 178t-178.5 118.5t-216.5 44q-246 0 -413 -185q-125 65 -284 65q-226 0 -399 -139t-220 -358q-136 -32 -241.5 -131t-146.5 -233v-4q-2 -5 -2 -10zM1722 1371q115 109 264 109q156 0 268 -112t112 -267 q0 -97 -54 -197q-153 153 -370 153h-36q-37 171 -184 314z" />
|
||||
<glyph unicode="" d="M-133 91q0 -40 29 -64q27 -28 65 -28h1018q37 0 62.5 27t25.5 65t-25.5 65t-62.5 27h-1018q-38 0 -66 -27.5t-28 -64.5zM149 414q0 -37 28 -62q26 -26 64 -26h1020q38 0 63 25t25 63t-25.5 64.5t-62.5 26.5h-1020q-38 0 -65 -26.5t-27 -64.5zM271 663q0 -12 20 -12h152 q14 0 24 15q36 87 112.5 144t169.5 64l58 8q18 0 18 19l8 54q17 173 147.5 290t306.5 117t306 -116t148 -291l8 -61q0 -20 18 -20h172q146 0 248.5 -101t102.5 -244q0 -142 -102.5 -244t-248.5 -102h-737q-18 0 -18 -18v-147q0 -19 18 -19h737q145 0 267.5 71t194 193 t71.5 266q0 113 -47 214q124 162 124 351q0 152 -75.5 281.5t-205 204.5t-282.5 75q-244 0 -410 -178q-136 65 -289 65q-227 0 -402 -140t-221 -359q-140 -32 -244.5 -128.5t-145.5 -231.5zM336 -239q0 -36 29 -62q26 -26 64 -26h1019q38 0 64.5 25t26.5 63t-27 65t-64 27 h-1019q-38 0 -65.5 -27.5t-27.5 -64.5zM1723 1369q108 104 263 104q158 0 269.5 -111t111.5 -268q0 -100 -53 -189q-157 153 -375 153h-34q-39 175 -182 311z" />
|
||||
<glyph unicode="" horiz-adv-x="2285" d="M3 529q0 -143 70 -264.5t191 -192.5t264 -71h1153q143 0 264.5 71t192.5 192.5t71 264.5q0 104 -44 213q121 148 121 352q0 152 -74.5 280.5t-203 203.5t-280.5 75q-239 0 -413 -186q-122 69 -286 69q-225 0 -398 -139t-222 -357q-179 -40 -292.5 -183t-113.5 -328z M185 529q0 133 89 230t224 113l73 3l7 77q22 173 150.5 289.5t300.5 116.5q115 0 214.5 -53t162.5 -146.5t74 -206.5l11 -80h190q141 0 243 -101.5t102 -241.5q0 -144 -101.5 -247t-243.5 -103h-1153q-139 0 -241 104t-102 246zM1469 1365q110 106 259 106 q158 0 268.5 -109.5t110.5 -267.5q0 -100 -54 -196q-153 153 -372 153h-33q-44 179 -179 314z" />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M-1 529q0 -213 148.5 -366t362.5 -164q19 0 19 19v142q0 19 -19 19q-137 7 -233 109t-96 241q0 133 90 231t224 114l56 8q20 0 20 19l8 54q17 173 147 289.5t305 116.5q174 0 305 -117t149 -289l6 -62q0 -19 20 -19h172q145 0 247.5 -101t102.5 -244q0 -139 -96 -241 t-233 -109q-21 0 -21 -19v-142q0 -19 21 -19q140 5 257.5 77t185 192.5t67.5 260.5q0 118 -46 214q126 153 126 354q0 151 -75.5 280t-204.5 204.5t-280 75.5q-249 0 -414 -185q-131 70 -289 70q-226 0 -401 -140.5t-225 -358.5q-176 -42 -291 -185.5t-115 -328.5zM571 -215 q14 -35 50 -49q32 -16 66.5 -2.5t47.5 47.5q14 35 1 69.5t-47 50.5q-32 13 -65.5 -1t-49.5 -46q-17 -28 -3 -69zM639 87q0 -25 16.5 -49t49.5 -33q36 -11 68.5 6t45.5 59l106 332q12 39 -8 71t-59 40q-35 11 -66.5 -6.5t-42.5 -53.5l-107 -339q0 -3 -1 -8.5t-1.5 -10 t-0.5 -8.5zM838 -511q0 -14 5 -31q14 -35 50 -48q13 -8 35 -8q10 0 32 6q35 13 50.5 48.5t-0.5 70.5t-48 49t-66 1q-31 -13 -44.5 -38.5t-13.5 -49.5zM917 -226q0 -28 16 -51t51 -30q3 0 12 -2t14 -2q69 5 86 66l187 647q11 39 -6 69.5t-53 41.5q-37 11 -69 -6.5t-43 -53.5 l-192 -647q0 -4 -1 -10.5t-1.5 -12t-0.5 -9.5zM1283 -183q0 -12 6 -34q13 -34 49 -47q15 -7 38 -7q19 0 31 6q36 14 49 46q13 35 0 69t-45 51q-35 13 -69.5 -1t-50.5 -46q-8 -17 -8 -37zM1360 88q0 -57 66 -80q22 -6 32 -6q20 0 36 9q28 14 43 59l105 332q12 37 -6.5 68.5 t-54.5 42.5q-37 11 -68 -6.5t-43 -53.5l-105 -334q-5 -27 -5 -31zM1470 1369q110 106 264 106q156 0 266.5 -111t110.5 -267q0 -99 -55 -196q-157 157 -373 157h-34q-49 185 -179 311z" />
|
||||
<glyph unicode="" horiz-adv-x="2285" d="M-6 525q0 -105 40 -200.5t108.5 -165t162.5 -112.5t199 -48q19 0 19 18v143q0 18 -19 18q-139 10 -234 110t-95 237q0 134 90.5 233t223.5 111l56 6q21 0 21 19l8 55q11 114 73.5 207t162 145.5t214.5 52.5q174 0 304 -115t149 -287l6 -62q0 -18 20 -18h171 q144 0 247 -102.5t103 -244.5q0 -137 -95 -237t-234 -110q-21 0 -21 -18v-143q0 -18 21 -18q214 10 361 161.5t147 364.5q0 102 -50 220q127 159 127 349q0 152 -75.5 281t-204 204t-279.5 75q-253 0 -412 -185q-130 68 -285 68q-225 0 -400 -140.5t-224 -359.5 q-179 -41 -292.5 -184t-113.5 -328zM810 32q-4 -22 15 -22h231l-141 -445h31l446 595q6 7 3 14.5t-14 7.5h-234l245 452q12 23 -15 23h-314q-12 0 -22 -15zM1457 1366q107 106 264 106t266.5 -110t109.5 -268q0 -95 -55 -192q-155 149 -368 149h-33q-47 190 -184 315z" />
|
||||
<glyph unicode="" horiz-adv-x="2308" d="M3 527q0 -139 68.5 -259t186.5 -192.5t259 -76.5q19 0 19 18v143q0 19 -19 19q-137 7 -234.5 109.5t-97.5 238.5q0 135 91.5 235t225.5 111l56 8q20 0 20 18l8 55q17 176 147.5 294.5t306.5 118.5q174 0 305.5 -118t149.5 -291l8 -62q0 -18 18 -18h174 q144 0 247.5 -103.5t103.5 -247.5q0 -136 -97.5 -238.5t-233.5 -109.5q-20 0 -20 -19v-143q0 -18 20 -18q141 4 258.5 76.5t185 192.5t67.5 259q0 118 -44 215q129 159 129 359q0 153 -75.5 282.5t-205 205t-281.5 75.5q-119 0 -229.5 -49.5t-190.5 -136.5q-141 69 -289 69 q-227 0 -403 -140.5t-226 -359.5q-180 -46 -294 -190t-114 -330zM573 -227q0 -27 17 -54t50 -37q37 -11 68.5 4t42.5 60l15 65q8 36 -10 67.5t-55 42.5q-36 11 -68.5 -8t-42.5 -57l-15 -63q-2 -6 -2 -20zM654 82q0 -35 26 -61q25 -27 61 -27q38 0 64 25.5t26 62.5t-26 62.5 t-64 25.5q-37 0 -62 -25t-25 -63zM719 325q-2 -25 14 -48.5t51 -34.5q33 -10 66.5 7.5t44.5 54.5l30 96q12 39 -7.5 69.5t-58.5 41.5q-35 11 -67 -7t-43 -53l-27 -98q-3 -27 -3 -28zM842 -560q0 -27 17 -52.5t52 -35.5q14 -3 26 -3q69 0 85 65l15 63q10 40 -9 72.5t-57 39.5 q-34 11 -66.5 -7.5t-43.5 -54.5l-15 -63q-4 -18 -4 -24zM926 -250q0 -36 26 -62t62 -26q38 0 63 25t25 63q0 37 -25 62t-63 25t-63 -25t-25 -62zM992 -8q-2 -24 14.5 -50t48.5 -32q37 -10 68 6t44 60l28 96q11 35 -7.5 67t-56.5 43q-35 11 -68 -8.5t-44 -56.5l-24 -96 q-3 -14 -3 -29zM1287 -237q0 -27 16 -51.5t49 -34.5q5 0 15 -2t15 -2q65 0 81 70l15 64q11 34 -7.5 67t-54.5 44q-39 10 -71.5 -8.5t-43.5 -56.5l-11 -63q0 -2 -1.5 -12t-1.5 -15zM1366 78q0 -37 26 -61q24 -26 62 -26t63 25t25 62q0 38 -25 63t-63 25t-63 -25t-25 -63z M1431 325q0 -27 17.5 -51.5t52.5 -34.5q3 0 12.5 -2t14.5 -2q17 0 39 10q33 17 43 56l27 96q10 36 -8 67.5t-54 42.5q-37 11 -68.5 -6t-42.5 -54l-30 -97q0 -3 -1.5 -11.5t-1.5 -13.5zM1480 1370q111 111 269 111q157 0 267.5 -111.5t110.5 -268.5q0 -105 -55 -197 q-154 154 -377 154h-34q-44 186 -181 312z" />
|
||||
<glyph unicode="" horiz-adv-x="2320" d="M-5 515q0 -181 107 -321t280 -192q15 -2 26 8l121 156q-143 0 -246.5 102.5t-103.5 246.5q0 138 91.5 239t228.5 112l56 8q18 0 18 15l8 60q19 176 150.5 294t307.5 118q178 0 310 -117t149 -292l8 -63q4 -18 22 -18h175q144 0 248 -105t104 -251q0 -135 -91.5 -235.5 t-224.5 -113.5q-76 0 -97 -30l-233 -256q-25 -29 -20 -66.5t34 -67.5q21 -28 62.5 -24.5t64.5 40.5l209 222q132 13 242.5 87.5t175 192t64.5 251.5q0 101 -46 222q124 158 124 354q0 156 -76 286.5t-207 206t-285 75.5q-251 0 -416 -182q-139 69 -296 69q-229 0 -405 -142 t-226 -366q-183 -41 -298 -186.5t-115 -336.5zM400 -285q0 -21 6 -34q13 -34 47 -47q36 -16 72.5 -2.5t48.5 48.5q16 35 2 71.5t-49 49.5q-36 13 -70 -0.5t-50 -47.5q-7 -15 -7 -38zM597 -24q0 -37 34 -71q68 -58 134 16l234 260q24 28 19 65.5t-34 60.5q-29 22 -66.5 17 t-62.5 -31l-236 -254q-22 -32 -22 -63zM665 -550q0 -19 8 -34q14 -36 45 -49q19 -8 39 -8q12 0 34 6q34 15 47 48q16 32 2 68t-48 49q-36 17 -69.5 3t-51.5 -51q-6 -18 -6 -32zM843 -295v-14q3 -38 35 -64q23 -29 63.5 -25.5t63.5 40.5l450 524q25 29 21 68t-37 61 q-28 23 -65 20t-62 -32l-449 -525q-20 -21 -20 -53zM1231 -384q-11 -36 0 -66q14 -35 48 -52q17 -8 38 -8q10 0 32 6q36 14 49 49q16 36 2.5 70t-47.5 47q-36 17 -70 3.5t-52 -49.5zM1487 1368q109 109 264 109q161 0 273 -112.5t112 -273.5q0 -100 -55 -194 q-156 156 -378 156h-34q-40 182 -182 315z" />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M1 525q0 -105 40 -200.5t108.5 -165t163 -112.5t199.5 -48q18 0 18 18v143q0 18 -18 18q-139 10 -234 110t-95 237q0 134 90.5 233.5t223.5 110.5l56 6q21 0 21 20l7 54q17 174 146 289.5t305 115.5q175 0 305 -114.5t148 -286.5l6 -62q0 -19 20 -19h171 q144 0 247 -102.5t103 -244.5q0 -137 -95 -237t-234 -110q-21 0 -21 -18v-143q0 -18 21 -18q214 10 362 161.5t148 364.5q0 112 -46 212q126 153 126 358q0 150 -75.5 279t-204.5 204.5t-279 75.5q-249 0 -414 -185q-141 69 -288 69q-226 0 -400.5 -140.5t-224.5 -360.5 q-176 -41 -291 -184.5t-115 -327.5zM586 -187q0 -64 69 -83q33 -11 67 6.5t44 53.5l160 611q10 35 -9.5 67t-57.5 43q-35 11 -67 -7.5t-42 -55.5l-160 -608q-4 -18 -4 -27zM863 -513q0 -19 9 -39q16 -33 54 -46q4 0 10.5 -1t12 -1.5t9.5 -0.5q69 0 81 70l246 932 q11 35 -7 67t-54 43q-39 11 -72 -7.5t-40 -55.5l-246 -933q-3 -15 -3 -28zM1306 -186q0 -25 17 -50t48 -34q11 -3 24 -3q27 0 52 14.5t34 48.5l160 611q12 33 -7 66t-55 44q-39 11 -70.5 -7.5t-38.5 -55.5l-160 -608q-4 -18 -4 -26zM1470 1362q107 107 264 107 q156 0 266 -109t110 -265q0 -100 -55 -197q-153 153 -373 153h-33q-45 187 -179 311z" />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M-1 526q0 -105 40 -200.5t108.5 -165.5t163.5 -113t200 -48q19 0 19 18v143q0 18 -19 18q-136 7 -232.5 109.5t-96.5 238.5t90 235t224 110l57 7q16 0 16 16l8 57q18 175 149 291.5t307 116.5q174 0 304.5 -115.5t149.5 -288.5l7 -61q0 -20 19 -20h173q142 0 244 -102 t102 -246q0 -136 -95 -238.5t-231 -109.5q-20 0 -20 -18v-143q0 -18 20 -18q214 10 362 162t148 365q0 100 -45 213q122 160 122 351q0 151 -75.5 280.5t-204.5 205t-280 75.5q-245 0 -412 -178q-139 69 -288 69q-227 0 -402 -141t-224 -361q-181 -42 -294.5 -183.5 t-113.5 -330.5zM574 -194q0 -27 15.5 -51.5t51.5 -36.5q18 -9 39.5 -7.5t43 21t29.5 51.5l30 108q10 40 -8.5 72t-56.5 39q-34 11 -67 -7.5t-44 -53.5l-30 -111q-3 -14 -3 -24zM714 315q1 -31 18 -55.5t51 -29.5q27 -5 32 -5q60 0 81 70l30 107q10 37 -8.5 70.5t-56.5 44.5 q-36 10 -68 -8.5t-43 -55.5l-32 -112q-4 -20 -4 -26zM846 -528q0 -28 16.5 -53t51.5 -35q22 -5 30 -5q14 0 40 11q27 13 41 59l32 108q10 40 -9 72.5t-56 39.5q-35 11 -68.5 -7.5t-44.5 -54.5l-30 -111q-3 -14 -3 -24zM987 -16q0 -27 17.5 -52.5t52.5 -35.5q36 -11 67.5 5 t43.5 60l30 108q11 40 -7.5 71t-56.5 38q-35 12 -68 -6.5t-44 -54.5l-30 -111q-5 -18 -5 -22zM1291 -202q-2 -25 14.5 -49.5t49.5 -35.5l28 -3q18 -1 40 8q33 13 44 58l31 112q11 37 -8 68.5t-55 42.5q-40 10 -71 -9t-38 -57l-31 -107q0 -3 -2 -12.5t-2 -15.5zM1435 310 q0 -28 17.5 -53t52.5 -32q1 0 11 -1.5t15 -1.5q70 0 87 66l30 110q10 40 -9 72t-57 39q-37 11 -68.5 -7.5t-41.5 -56.5l-32 -109q-5 -22 -5 -26zM1472 1366q107 103 261 103q156 0 266 -111.5t110 -267.5q0 -102 -51 -189q-154 154 -372 154h-35q-40 176 -179 311z" />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M-5 529q0 -213 149 -366.5t363 -163.5q20 0 20 18v143q0 18 -20 18q-137 8 -233.5 110t-96.5 241q0 133 91 231t225 114l56 4q20 0 20 19l8 58q17 173 147 290t305 117q174 0 304.5 -117t148.5 -290l8 -61q0 -20 19 -20h172q145 0 248 -101.5t103 -243.5 q0 -139 -96.5 -241t-233.5 -110q-21 0 -21 -18v-143q0 -18 21 -18q214 7 362.5 161.5t148.5 368.5q0 114 -46 214q126 154 126 354q0 152 -75.5 281.5t-204.5 204.5t-280 75q-248 0 -415 -185q-129 69 -289 69q-226 0 -401.5 -140.5t-225.5 -358.5q-177 -42 -292 -185.5 t-115 -328.5zM677 90q0 -35 26 -61q27 -27 62 -27q37 0 62.5 25t25.5 63t-25 63t-63 25t-63 -25t-25 -63zM677 -297q0 -38 26 -62q26 -26 62 -26q38 0 63 25t25 63t-25.5 64.5t-62.5 26.5t-62.5 -26.5t-25.5 -64.5zM1017 -112q0 -37 27 -65.5t62 -28.5q37 0 64.5 28t27.5 66 q0 35 -27.5 61.5t-64.5 26.5q-35 0 -62 -26.5t-27 -61.5zM1017 271q0 -36 26 -62t63 -26q38 0 65 25.5t27 62.5t-27 63.5t-65 26.5q-36 0 -62.5 -26.5t-26.5 -63.5zM1017 -504q0 -37 26.5 -64t62.5 -27q38 0 65 27t27 64q0 35 -27.5 61.5t-64.5 26.5q-35 0 -62 -26.5 t-27 -61.5zM1362 90q0 -32 27 -61q27 -27 64 -27t62.5 25t25.5 63t-25 63t-63 25t-64.5 -25t-26.5 -63zM1362 -297q0 -35 27 -62q26 -26 64 -26t63 25t25 63t-25.5 64.5t-62.5 26.5t-64 -27t-27 -64zM1467 1369q108 108 266 108q157 0 266.5 -111t109.5 -269q0 -94 -54 -196 q-154 154 -374 154h-33q-47 186 -181 314z" />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M-2 529q0 -213 148.5 -366.5t363.5 -163.5q18 0 18 18v146q0 20 -18 20q-140 10 -235.5 110t-95.5 236q0 135 91 234.5t225 110.5l56 7q20 0 20 20l7 53q17 173 147 290t306 117q175 0 305 -116.5t149 -290.5l6 -61q0 -19 20 -19h171q145 0 248 -101.5t103 -243.5 q0 -136 -95 -236t-234 -110q-22 0 -22 -20v-146q0 -18 22 -18q213 7 361.5 161.5t148.5 368.5q0 118 -46 214q126 153 126 358q0 151 -75.5 280.5t-204.5 205t-280 75.5q-244 0 -419 -187q-132 67 -284 67q-226 0 -401.5 -140t-224.5 -359q-177 -42 -292 -185.5t-115 -328.5 zM631 435q0 -60 45.5 -104t108.5 -44t106.5 43t43.5 105q0 41 -37.5 109t-70.5 107q-3 4 -19.5 21.5t-22.5 25.5l-38 -43q-44 -48 -80 -112.5t-36 -107.5zM950 10q0 -101 73.5 -175t175.5 -74q103 0 177 74t74 175q0 43 -25 103t-60 111q-74 95 -138 159q-9 7 -28 26 l-62 -62q-71 -68 -129 -166.5t-58 -170.5zM1107 725q0 -43 30 -71.5t76 -28.5q41 0 70 28.5t29 71.5q0 65 -99 172l-27 -28q-30 -32 -54.5 -74.5t-24.5 -69.5zM1469 1369q107 106 265 106q156 0 266 -109t110 -265q0 -101 -54 -197q-160 154 -374 154h-33q-45 188 -180 311z " />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M-1 533q0 -176 106 -317.5t274 -191.5l-68 -177q-7 -22 15 -22h226l-122 -436h31l435 586q6 7 1.5 15t-15.5 8h-232l264 498q12 23 -15 23h-315q-16 0 -21 -15l-117 -312q-114 29 -189.5 125t-75.5 216q0 134 90.5 233.5t224.5 111.5l56 7q21 0 21 18l8 55 q17 174 146.5 290.5t305.5 116.5q175 0 305 -116.5t149 -290.5l7 -62q0 -18 19 -18h173q145 0 248 -101.5t103 -243.5q0 -137 -96 -237.5t-235 -110.5q-20 0 -20 -19v-147q0 -18 20 -18q213 7 361.5 162t148.5 370q0 114 -45 213q123 161 123 351q0 114 -45 217.5 t-120 178.5t-179 119.5t-217 44.5q-118 0 -226 -48t-186 -134q-131 70 -288 70q-227 0 -402 -139.5t-225 -359.5q-177 -41 -292 -185t-115 -328zM871 -520q0 -28 17 -54.5t49 -32.5q1 0 11 -1.5t15 -1.5q69 5 86 65l31 113q10 35 -9.5 67.5t-56.5 43.5q-35 10 -67.5 -9 t-43.5 -57l-28 -107q-4 -20 -4 -26zM1014 -11q0 -24 16.5 -48t49.5 -36q35 -12 67 5.5t43 56.5l32 111q10 40 -8.5 72t-56.5 39q-36 11 -69 -7.5t-45 -56.5l-26 -109q0 -3 -1 -8.5t-1.5 -10t-0.5 -8.5zM1315 -184q0 -30 17.5 -55.5t50.5 -34.5q25 -5 28 -5q64 0 83 64 l26 113q11 35 -6 67t-53 44q-40 10 -73.5 -9.5t-40.5 -56.5l-29 -106q-3 -12 -3 -21zM1461 322q0 -26 17 -50.5t52 -36.5q27 -3 28 -3q19 0 40 9q31 16 42 56l31 111q10 35 -9.5 67.5t-56.5 43.5q-36 11 -68 -7.5t-43 -56.5l-30 -109q-3 -14 -3 -24zM1472 1373 q106 102 261 102q157 0 267 -110.5t110 -267.5q0 -101 -52 -190q-158 154 -372 154h-35q-49 186 -179 312z" />
|
||||
<glyph unicode="" horiz-adv-x="2297" d="M2 529q0 -178 106 -318t274 -187l-69 -179q-8 -23 15 -23h226l-111 -447h30l423 600q6 7 1.5 15t-15.5 8h-232l264 492q11 23 -15 23h-314q-14 0 -24 -15l-114 -306q-114 28 -188.5 122t-74.5 215q0 133 89.5 230.5t223.5 113.5l57 4q20 0 20 19l8 57q17 173 146 289.5 t304 116.5q173 0 303 -117t148 -289l8 -60q0 -20 19 -20h172q142 0 245.5 -102t103.5 -242q0 -138 -96 -239.5t-232 -108.5q-21 0 -21 -19v-143q0 -18 21 -18q139 4 256 76.5t184 192.5t67 259q0 119 -44 214q124 146 124 353q0 150 -75 279t-203.5 204t-278.5 75 q-248 0 -413 -185q-129 69 -288 69q-225 0 -400 -139.5t-224 -357.5q-176 -41 -291 -184.5t-115 -327.5zM848 -525q0 -26 15.5 -49t48.5 -33q3 0 8.5 -1t10 -1.5t8.5 -0.5q67 0 85 64l259 948q10 37 -7 68.5t-52 42.5q-37 11 -69.5 -6.5t-42.5 -53.5l-261 -949 q-3 -27 -3 -29zM1290 -201q0 -26 16 -50t51 -35q3 0 8.5 -1t10 -1.5t8.5 -0.5q19 0 38 8q31 13 44 59l175 624q10 37 -8 68.5t-54 42.5q-37 11 -68.5 -6.5t-41.5 -53.5l-174 -628q-5 -23 -5 -26zM1469 1367q108 102 264 102q155 0 264.5 -109t109.5 -264q0 -103 -53 -197 q-154 154 -372 154h-34q-45 184 -179 314z" />
|
||||
<glyph unicode="" horiz-adv-x="1131" d="M1 1160q0 80 57 137t137 57q79 0 135.5 -57t56.5 -137t-56.5 -137t-135.5 -57t-136.5 57t-57.5 137zM95 1160q0 -41 30 -71t70 -30q41 0 71 30t30 71t-30 71t-71 30q-42 0 -71 -29.5t-29 -71.5zM510 688q0 -123 68 -219q35 -50 98.5 -79.5t144.5 -29.5q233 0 292 178 q6 23 -6.5 43.5t-35.5 24.5q-23 6 -43 -7t-25 -36q0 -1 -1.5 -5.5l-2.5 -7.5q-18 -30 -48 -48q-50 -30 -130 -30q-51 0 -90 17q-64 27 -91 95q-18 44 -18 104v344q0 24 3 48q6 61 48 111q47 56 148 56q82 0 130 -29q32 -19 48 -48q1 -3 2.5 -8.5t1.5 -6.5q6 -22 25 -32.5 t43 -5.5q23 5 35.5 24.5t6.5 42.5v1l-9 25q-8 18 -29.5 46t-48.5 47q-77 56 -205 56q-81 0 -144 -28.5t-98 -77.5q-69 -95 -69 -221v-344z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M3 531q0 -214 149 -367t363 -163q19 0 19 18v143q0 19 -19 19q-137 7 -233.5 109t-96.5 241q0 133 91 231.5t225 114.5l56 3q20 0 20 18l8 59q16 173 146 289.5t306 116.5q174 0 304.5 -116.5t148.5 -289.5l8 -62q0 -18 19 -18h172q142 0 246.5 -103t104.5 -243 q0 -139 -96.5 -241t-233.5 -109q-21 0 -21 -19v-143q0 -18 21 -18q213 7 361 161t148 369q0 144 -71 265t-193 190.5t-266 69.5h-34q-52 214 -224.5 351t-393.5 137q-226 0 -401.5 -140t-225.5 -359q-176 -41 -291.5 -185.5t-115.5 -328.5zM746 368q0 -37 27 -64l275 -278 q20 -25 62 -25q45 0 65 25l276 278q27 29 27 64q0 37 -26.5 62t-64.5 25t-66 -25l-120 -118v425q0 38 -26.5 63t-64.5 25t-63 -25t-25 -63v-425l-118 118q-28 25 -66 25q-40 0 -66 -24.5t-26 -62.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M6 527q0 -105 40 -200.5t108.5 -165t163 -112.5t199.5 -48q18 0 18 18v142q0 20 -18 20q-139 10 -234.5 110t-95.5 236q0 134 91 233.5t224 110.5l56 8q20 0 20 18l8 55q11 114 74 207.5t162.5 146t214.5 52.5q175 0 305 -115t148 -288l7 -61q0 -19 20 -19h172 q144 0 247 -103t103 -245q0 -136 -95 -236t-234 -110q-21 0 -21 -20v-142q0 -18 21 -18q214 10 361 161.5t147 364.5q0 143 -71 264.5t-193 192.5t-265 71h-34q-53 213 -225.5 350t-392.5 137q-225 0 -400.5 -141.5t-225.5 -360.5q-176 -41 -290.5 -185t-114.5 -328z M670 392q0 -119 59.5 -220.5t161 -161.5t219.5 -60q184 0 314.5 130.5t130.5 311.5q0 38 -26.5 64.5t-64.5 26.5t-66 -27t-28 -64q0 -108 -76 -184.5t-184 -76.5q-107 0 -183.5 77t-76.5 184q0 96 57.5 171t140.5 82l-45 -42q-24 -24 -24 -61q0 -40 24 -70q22 -24 57 -25 t75 25l194 199q26 26 26 62q0 41 -26 65l-194 195q-30 28 -66 28q-37 0 -63.5 -27t-26.5 -65t24 -62l38 -38q-160 -27 -265.5 -149t-105.5 -288z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M0 530q0 -213 148.5 -366t362.5 -163q18 0 18 18v142q0 20 -18 20q-137 7 -233 108.5t-96 240.5q0 132 90 230t224 114h56q21 0 21 19l6 61q17 173 147 290t305 117q173 0 303.5 -117t148.5 -290l8 -61q0 -19 19 -19h172q142 0 246 -102.5t104 -241.5q0 -138 -96.5 -240 t-232.5 -109q-21 0 -21 -20v-142q0 -18 21 -18q139 4 256 76t184.5 192.5t67.5 260.5q0 107 -42 204t-113 167t-169 111.5t-205 41.5h-34q-53 214 -225 350.5t-392 136.5q-226 0 -401 -140.5t-224 -358.5q-177 -41 -291.5 -184.5t-114.5 -327.5zM741 463q0 -40 26 -68 q24 -24 65 -24q39 0 66 24l118 122v-424q0 -38 25 -65t63 -27q37 0 64 27t27 65v420l120 -118q64 -49 130 0q26 24 26 66q0 38 -26 66l-276 274q-26 26 -64 26q-39 0 -63 -26l-275 -274q-26 -26 -26 -64z" />
|
||||
<glyph unicode="" horiz-adv-x="2217" d="M3 531q0 -214 149 -367t363 -163q19 0 19 18v143q0 19 -19 19q-137 7 -233.5 109t-96.5 241q0 133 91 231.5t225 114.5h56q20 0 20 18l8 62q16 173 146 289.5t306 116.5q174 0 304.5 -116.5t148.5 -289.5l8 -62q0 -18 19 -18h172q142 0 246.5 -103t104.5 -243 q0 -139 -96.5 -241t-233.5 -109q-21 0 -21 -19v-143q0 -18 21 -18q213 7 361 161t148 369q0 144 -71 265t-193 190.5t-266 69.5h-34q-52 214 -224.5 351t-393.5 137q-226 0 -401.5 -140t-225.5 -359q-176 -41 -291.5 -185.5t-115.5 -328.5z" />
|
||||
<glyph unicode="" horiz-adv-x="377" d="M-3 1349q0 80 57 137t137 57q79 0 135.5 -57t56.5 -137t-56.5 -137.5t-135.5 -57.5t-136.5 57.5t-57.5 137.5zM90 1349q0 -41 30 -71t71 -30t70.5 30t29.5 71t-29.5 70.5t-70.5 29.5q-42 0 -71.5 -29t-29.5 -71z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M6 542q0 -31 20.5 -51.5t50.5 -20.5h306q30 0 50.5 20.5t20.5 51.5q0 30 -20.5 49.5t-50.5 19.5h-133l415 414q18 21 18 53q0 30 -18 49q-20 19 -54 19q-31 0 -50 -19l-412 -413v133q0 31 -20.5 51.5t-51.5 20.5q-30 0 -50.5 -21t-20.5 -51v-305z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M-6 574q0 -34 28 -59l256 -261q25 -25 61 -25q38 0 63 25l256 261q27 24 27 59q0 36 -24.5 60.5t-60.5 24.5t-61 -25l-113 -112v703q0 36 -25.5 60t-61.5 24t-61 -24t-25 -60v-703l-114 112q-25 25 -59 25q-36 0 -61 -24.5t-25 -60.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1131" d="M3 1157q0 79 58 137q57 57 137 57q79 0 135.5 -57t56.5 -137t-56.5 -137.5t-135.5 -57.5q-80 0 -137.5 58t-57.5 137zM97 1157q0 -41 30 -71t71 -30t70.5 30t29.5 71t-29.5 70.5t-70.5 29.5q-42 0 -71.5 -29t-29.5 -71zM568 422q0 -23 16.5 -39.5t39.5 -16.5t39.5 16.5 t16.5 39.5v404h305q23 0 39.5 17t16.5 40q0 24 -16 40t-40 16h-305v291h408q23 0 38.5 16.5t15.5 39.5t-15.5 39.5t-38.5 16.5h-509q-11 0 -11 -12v-908z" />
|
||||
<glyph unicode="" horiz-adv-x="2285" d="M-13 635q0 42 29 66q23 24 66 24h222q39 0 64.5 -25.5t25.5 -64.5q0 -38 -26 -65t-64 -27h-222q-39 0 -67 27t-28 65zM87 93q0 38 27 65q26 25 65 25h1942q39 0 66.5 -26t27.5 -64t-28 -65.5t-66 -27.5h-1942q-38 0 -65 27.5t-27 65.5zM304 1391q0 41 25 63q27 29 66 29 t66 -29l154 -156q27 -26 27 -64q0 -40 -26 -65.5t-64 -25.5q-35 0 -64 26l-159 157q-25 22 -25 65zM582 635q0 -139 57 -249q5 -15 25 -15h178q12 0 14.5 6.5t-7.5 17.5q-84 103 -84 240q0 159 114 271t272 112q159 0 271.5 -112t112.5 -271q0 -136 -86 -240q-6 -10 -6 -13 q-1 -5 3 -8t11 -3h182q14 0 22 15q59 111 59 249q0 153 -76.5 284.5t-208 208.5t-284.5 77t-284.5 -77t-208 -208.5t-76.5 -284.5zM1058 1481v223q0 38 27.5 66t65.5 28t66 -28t28 -66v-223q0 -38 -28 -66t-66 -28t-65.5 28t-27.5 66zM1658 1234q0 38 27 64l154 156 q27 29 65 29q40 0 67 -26.5t27 -65.5q0 -41 -24 -65l-161 -157q-26 -24 -63 -24q-40 -1 -66 24t-26 65zM1906 635q0 42 27 66q23 24 62 24h223q39 0 66.5 -25.5t27.5 -64.5q0 -38 -28 -65t-66 -27h-223q-37 0 -63 27t-26 65z" />
|
||||
<glyph unicode="" horiz-adv-x="2285" d="M73 94q0 42 30 66q22 25 67 25h1956q40 0 68 -26t28 -65q0 -38 -28 -66.5t-68 -28.5h-1956q-40 0 -68.5 28.5t-28.5 66.5zM283 978q0 41 26 67q27 28 68 28q37 0 64 -28l160 -160q29 -29 29 -67q0 -37 -29 -66q-24 -29 -64 -28.5t-68 28.5l-160 160q-26 25 -26 66z M597 382q-7 -25 16 -25h158q11 0 24 18q48 102 142 162t209 60q116 0 212 -60t144 -162q13 -18 24 -18h159q20 0 16 25q-54 180 -208 293.5t-347 113.5q-192 0 -343.5 -113t-205.5 -294zM1055 1071v228q0 40 26 68t65 28q40 0 67 -27.5t27 -68.5v-228q0 -41 -27 -68t-67 -27 q-39 0 -65 27.5t-26 67.5zM1665 818q0 37 28 67l163 160q25 28 66 28q39 0 64 -27t25 -68q0 -42 -25 -66l-157 -160q-27 -27 -61 -30q-36 -4 -69.5 26t-33.5 70z" />
|
||||
<glyph unicode="" horiz-adv-x="1085" d="M6 734q0 -38 25 -63l262 -256q23 -26 58 -26q36 0 61 24t25 60q0 35 -26 61l-112 112h703q36 0 60 25.5t24 61.5t-24 61.5t-60 26.5h-703l112 113q26 26 26 59q0 36 -25 61t-61 25q-33 0 -58 -28l-262 -256q-25 -25 -25 -61z" />
|
||||
<glyph unicode="" horiz-adv-x="2285" d="M-288 99q0 -36 27 -61t66 -25h1985q38 0 64.5 25t26.5 61q0 39 -26 65.5t-65 26.5h-1985q-38 0 -65.5 -27t-27.5 -65zM-10 431q0 -38 28 -63q22 -29 63 -29h1985q37 0 62 27t25 65q0 37 -25 62t-62 25h-1985q-38 0 -64.5 -25t-26.5 -62zM6 689v5q-7 -24 13 -24h154 q9 0 20 16q38 83 113.5 136t165.5 60l57 8q20 0 20 19l6 53q17 172 145.5 287.5t302.5 115.5q172 0 301 -114t147 -285l7 -61q0 -19 22 -19h169q103 0 187 -55t125 -145q11 -16 23 -16h151q19 0 16 24q-35 89 -49 113q116 104 160 274l18 70q4 10 -1.5 17t-12.5 7l-66 23 q-143 41 -217.5 169t-39.5 273l14 62q8 15 -14 25l-90 25q-175 43 -343 -28t-263 -226q-127 49 -244 49q-222 0 -395.5 -140t-223.5 -357q-135 -32 -236.5 -129t-141.5 -232zM175 -226q0 -38 28 -63q27 -29 63 -29h1989q37 0 63 27t26 65q0 37 -26 62t-63 25h-1989 q-38 0 -64.5 -25t-26.5 -62zM1402 1403q56 92 150.5 142t199.5 40q-11 -167 75 -312.5t237 -215.5q-24 -56 -80 -114q-147 121 -335 121h-34q-51 210 -213 339z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M-2 741q0 -192 134 -326.5t326 -134.5q30 0 51.5 23t21.5 54t-21 51.5t-52 20.5q-130 0 -220.5 91t-90.5 221q0 124 85.5 216t200.5 92l-35 -34q-24 -23 -22 -52q0 -29 21 -51.5t52 -22.5q32 0 54 22l161 160q21 17 21 54q0 35 -21 50l-161 163q-21 22 -53 22 q-31 0 -53 -22t-22 -53q0 -33 23 -54l32 -30q-184 -13 -308 -144.5t-124 -315.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1108" d="M-7 674q0 -151 75.5 -279.5t204 -203t278.5 -74.5q153 0 281.5 74t202.5 202t74 281q0 38 -25.5 65t-62.5 27t-64.5 -27t-27.5 -65q0 -157 -110.5 -267.5t-267.5 -110.5q-155 0 -264 110.5t-109 267.5q0 136 84.5 246.5t196.5 117.5l-41 -39q-26 -28 -26 -62 q0 -36 26 -64q58 -56 129 0l196 194q26 20 26 66q0 41 -26 61l-196 198q-28 26 -61 26q-40 0 -67 -26.5t-27 -64.5q0 -39 26 -65l41 -38q-200 -35 -333 -191.5t-133 -358.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1085" d="M0 799q0 -36 24 -61t59 -21h703l-111 -115q-25 -25 -25 -59q0 -36 25.5 -61t61.5 -25q34 1 57 29l261 257q25 25 25 62q-2 37 -26 62l-263 255q-24 26 -58 25q-36 0 -61 -24t-25 -60t25 -61l113 -115h-703q-36 -1 -59.5 -26.5t-22.5 -61.5z" />
|
||||
<glyph unicode="" horiz-adv-x="857" d="M2 1027q0 41 40.5 108t77.5 111q10 12 25 29.5t17 19.5l39 -46q44 -49 81 -114t37 -108q0 -66 -45.5 -113t-111.5 -47t-113 47t-47 113zM335 584q0 46 26 107.5t64 113.5q31 41 75 91.5t66 71.5q4 2 27 26l28 -26q59 -55 140 -162q41 -55 67 -115t26 -107 q0 -109 -75.5 -184t-185.5 -75q-108 0 -183 76t-75 183zM497 1320q0 68 108 181l26 -30q30 -35 54.5 -78.5t24.5 -72.5q0 -44 -30.5 -73.5t-74.5 -29.5q-46 0 -77 29.5t-31 73.5z" />
|
||||
<glyph unicode="" d="M6 521q0 -40 29 -66q26 -30 68 -30h1567q46 0 77.5 -32t31.5 -79q0 -46 -31 -76.5t-78 -30.5t-78 31q-26 28 -64 28q-40 0 -68.5 -27.5t-28.5 -65.5q0 -40 30 -67q90 -88 209 -88q125 0 214 86t89 210t-89.5 213.5t-213.5 89.5h-1567q-40 0 -68.5 -28t-28.5 -68zM6 871 q0 -38 29 -65q28 -28 68 -28h2138q125 0 214.5 87t89.5 210q0 124 -89.5 212t-214.5 88q-123 0 -208 -85q-30 -27 -30 -71q0 -41 27.5 -67t67.5 -26t68 26q30 33 75 33q46 0 77.5 -32t31.5 -78t-31.5 -77t-77.5 -31h-2138q-40 0 -68.5 -28t-28.5 -68z" />
|
||||
<glyph unicode="" d="M-40 693q0 40 32 74q36 31 75 31h248q43 0 72 -31t29 -74q0 -46 -29 -77t-72 -31h-248q-43 0 -75 32.5t-32 75.5zM315 1544q0 43 28 73q36 31 75 31q42 0 73 -31l175 -176q30 -35 30 -74q0 -45 -29 -75t-70 -30q-39 0 -75 31l-179 173q-28 34 -28 78zM528 104q0 45 31 73 q28 28 73 28h281l332 312q16 13 36 0l337 -312h295q43 0 73.5 -29.5t30.5 -71.5q0 -43 -30.5 -74t-73.5 -31h-361q-16 0 -31 8l-257 242l-255 -242q-13 -8 -30 -8h-347q-43 0 -73.5 31t-30.5 74zM627 693q0 -155 66 -282q4 -19 27 -19h201q12 0 16 9t-2 20 q-102 123 -102 272q0 180 128 306t308 126q179 0 305.5 -126t126.5 -306q0 -150 -101 -272q-7 -11 -3.5 -20t16.5 -9h203q21 0 25 19q66 123 66 282q0 130 -51 248t-136.5 203.5t-203.5 136t-247 50.5q-130 0 -248.5 -50.5t-205 -136t-137.5 -203.5t-51 -248zM1163 1648v245 q0 46 30 75.5t76 29.5q45 0 74.5 -30t29.5 -75v-245q0 -46 -29.5 -75.5t-74.5 -29.5q-46 0 -76 29.5t-30 75.5zM1840 1367q0 40 29 74l173 176q31 31 75 31t74 -30.5t30 -73.5q0 -46 -28 -78l-180 -173q-34 -31 -75 -31q-43 0 -70.5 29.5t-27.5 75.5zM2119 693q0 43 28.5 74 t70.5 31h251q43 0 74 -31t31 -74q0 -44 -31 -76t-74 -32h-251q-43 0 -71 31t-28 77z" />
|
||||
<glyph unicode="" d="M-22 681q0 44 32 72q28 28 73 28h246q43 0 71.5 -28.5t28.5 -71.5q0 -44 -28.5 -75t-71.5 -31h-246q-43 0 -74 31.5t-31 74.5zM329 1519q0 44 28 72q32 32 74 32q46 0 72 -32l174 -174q74 -70 0 -144q-30 -30 -70 -30q-35 0 -72 30l-178 174q-28 30 -28 72zM539 103 q0 42 32 74q29 29 72 29h343q17 0 30 -8l251 -237l255 237q11 8 31 8h352q43 0 73.5 -30t30.5 -73t-30.5 -73.5t-73.5 -30.5h-286l-334 -303q-20 -14 -36 0l-329 303h-277q-43 0 -73.5 30.5t-30.5 73.5zM639 681q0 -157 63 -280q8 -17 28 -17h199q13 0 16 8t-8 19 q-95 119 -95 270q0 176 126 299.5t304 123.5q176 0 301.5 -124t125.5 -299q0 -152 -94 -270q-11 -11 -8 -19t16 -8h201q20 0 25 17q66 125 66 280q0 127 -50.5 244.5t-135.5 202.5t-202 135.5t-245 50.5t-245 -50.5t-202 -135.5t-135.5 -202.5t-50.5 -244.5zM1168 1621v248 q0 43 30.5 73.5t73.5 30.5t73.5 -30.5t30.5 -73.5v-248q0 -43 -30.5 -73.5t-73.5 -30.5t-73.5 30.5t-30.5 73.5zM1838 1345q0 46 27 72l174 174q26 32 72 32q44 0 73.5 -30.5t29.5 -73.5q0 -44 -28 -72l-177 -174q-37 -30 -74 -30q-42 0 -69.5 29.5t-27.5 72.5zM2113 681 q0 43 28.5 71.5t71.5 28.5h246q43 0 73.5 -29t30.5 -71q0 -43 -30.5 -74.5t-73.5 -31.5h-246q-43 0 -71.5 31t-28.5 75z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M-1 393q0 86 39.5 160.5t111.5 124.5v668q0 81 55.5 137t136.5 56t137 -56t56 -137v-668q71 -50 110.5 -124.5t39.5 -160.5q0 -143 -100.5 -243t-242.5 -100t-242.5 100t-100.5 243zM117 393q0 -94 66 -160.5t159 -66.5q94 0 161.5 67.5t67.5 159.5q0 63 -32.5 116.5 t-88.5 83.5l-19 9q-10 4 -10 20v724q0 32 -22.5 54t-56.5 22q-33 0 -56 -22t-23 -54v-724q0 -16 -9 -20l-20 -9q-55 -30 -86 -83t-31 -117z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M153 401q0 -81 56 -137.5t134 -56.5q79 0 136 56.5t57 137.5q0 71 -49 126t-120 66v558q0 7 -7 14.5t-17 7.5q-22 0 -22 -22v-558q-70 -11 -119 -66t-49 -126z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M-10 377q0 87 40.5 163t113.5 126v681q0 82 56 139.5t138 57.5q83 0 140 -57.5t57 -139.5v-681q72 -51 112.5 -126.5t40.5 -162.5q0 -145 -102.5 -247.5t-247.5 -102.5t-246.5 102.5t-101.5 247.5zM110 377q0 -96 67 -164t161 -68q97 0 166 68.5t69 163.5q0 64 -33 118 t-91 84l-19 11q-11 5 -11 19v738q0 32 -23.5 54.5t-57.5 22.5q-32 0 -55.5 -22.5t-23.5 -54.5v-738q0 -15 -10 -19l-19 -11q-57 -30 -88.5 -83.5t-31.5 -118.5zM170 381q0 -72 49 -122.5t119 -50.5t121 50.5t51 122.5q0 64 -44 113t-106 57v495q0 6 -7 12.5t-15 6.5 q-19 0 -19 -19v-495q-62 -8 -105.5 -57t-43.5 -113z" />
|
||||
<glyph unicode="" horiz-adv-x="1485" d="M5 718q0 -71 74 -121q135 -95 408 -95q122 0 227 21q111 24 181.5 75.5t70.5 119.5q0 21 -8 42q142 35 223 94.5t81 136.5q0 19 -6 41q233 83 233 224q0 90 -102 160q-200 133 -586 133q-181 0 -329 -32q-159 -33 -258 -102.5t-99 -158.5q0 -51 34 -97 q-122 -69 -122 -168q0 -76 76 -135q-98 -57 -98 -138zM46 411q0 -75 92 -117.5t232 -42.5q142 0 235 42.5t93 117.5q0 28 -18 47t-46 19q-23 0 -41 -16t-23 -39q-20 -16 -75 -29.5t-125 -13.5q-113 0 -183 32q16 16 17.5 41t-10.5 42q-16 22 -41.5 27t-47.5 -9 q-59 -40 -59 -101zM133 718q1 2 12 12q9 9 38.5 23t65.5 24l8 4q166 -55 388 -55q97 0 176 11l18 -16q-9 -16 -44 -34q-41 -22 -126.5 -39t-181.5 -17t-182.5 17t-128.5 39q-34 15 -43 31zM141 143q0 -65 73.5 -100t182.5 -35q111 0 185.5 35t74.5 100q0 26 -19 46t-45 20 q-48 0 -63 -49q-40 -25 -133 -25q-83 0 -132 25q-15 49 -63 49q-26 0 -43.5 -19t-17.5 -47zM154 991q0 6 11 19q25 31 97 60q196 -105 539 -105q175 0 329 32v-6q0 -16 -18 -31q-42 -37 -157 -70q-124 -37 -310 -37q-188 0 -312 37q-119 33 -159 70q-20 16 -20 31zM243 1256 q0 18 24 40q46 43 183 83q146 43 351 43q206 0 354 -43q138 -40 183 -83q23 -23 23 -40t-23 -38q-45 -43 -183 -84q-148 -43 -354 -43q-205 0 -351 43q-138 40 -183 84q-24 21 -24 38z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M5 557q0 -31 18 -50q20 -19 54 -19q31 0 50 19l411 413v-133q0 -31 20.5 -51.5t51.5 -20.5q30 0 50.5 21t20.5 51v306q0 31 -20.5 51.5t-50.5 20.5h-306q-30 0 -50.5 -20.5t-20.5 -51.5q0 -30 20.5 -50t50.5 -20h133l-414 -414q-18 -21 -18 -52z" />
|
||||
<glyph unicode="" horiz-adv-x="685" d="M-2 1013q-1 -36 23 -61.5t60 -24.5q36 -2 61 25l113 112v-703q-1 -36 24.5 -60t62.5 -23q35 -2 61 22t27 60v703l112 -112q24 -25 59 -25q37 0 62 24.5t25 60.5q-2 37 -27 58l-255 262q-25 24 -63 27q-38 -2 -63 -28l-256 -260q-26 -22 -26 -57z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M10 769q0 156 60.5 298.5t163 244.5t244 163t297.5 61q157 0 299 -61t245 -163.5t164 -244.5t61 -297q0 -156 -61 -298.5t-164 -245.5t-245 -163.5t-298 -60.5q-155 0 -297 60.5t-244.5 163t-163.5 244.5t-61 299zM178 769q0 -162 80.5 -299.5t218.5 -217t299 -79.5 q121 0 232 47.5t191.5 127.5t128 190.5t47.5 231.5q0 245 -177 422q-178 176 -423 176q-121 0 -231.5 -48t-190.5 -128t-127.5 -191t-47.5 -232zM502 521l89 239q5 10 0 21l-89 235q-5 10 0.5 16t16.5 1l599 -252q10 -1 10 -11q0 -9 -10 -10l-599 -257q-11 -4 -16.5 1.5 t-0.5 16.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M26 968q22 82 64 161t108.5 154t149 131.5t193 90.5t233.5 34q319 0 544 -226q148 -148 201.5 -346t0.5 -397q-22 -82 -63.5 -161t-107.5 -154t-148 -131.5t-193 -91t-234 -34.5q-320 0 -545 226q-148 147 -202 346t-1 398zM173 769q0 -249 176 -425t425 -176 q122 0 233 47.5t191.5 128t128 191.5t47.5 234q0 163 -80.5 301t-218.5 218.5t-301 80.5q-123 0 -234 -47.5t-191.5 -128t-128 -191.5t-47.5 -233zM392 761q0 7 11 10l605 250q11 2 16 -3.5t1 -16.5l-248 -604q-2 -11 -10 -11q-11 0 -16 11l-103 230q-9 14 -15 15l-230 104 q-11 4 -11 15z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M26 568.5q-53 198.5 0 396.5q22 82 63.5 160.5t107.5 153t148 131t192.5 90.5t233.5 34q317 0 542 -225q148 -147 201 -345t0 -396q-22 -82 -63 -160.5t-107 -153.5t-148 -131.5t-192 -90.5t-233 -34q-319 0 -544 225q-148 147 -201 345.5zM171 767q0 -249 176 -424 q175 -176 424 -176q162 0 299.5 80.5t218 218.5t80.5 301q0 162 -80.5 299.5t-218 218t-299.5 80.5q-163 0 -301 -80.5t-218.5 -218t-80.5 -299.5zM519 998q-2 11 3.5 17t15.5 2l603 -249q11 -2 11 -10q0 -9 -11 -14l-230 -104q-11 -4 -15 -15l-104 -230q-5 -11 -14 -11 q-8 0 -10 11z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M2 765q0 209 103.5 386.5t280.5 280.5t385 103q156 0 298 -61t245 -164t164 -245.5t61 -299.5q0 -156 -61 -298.5t-164 -245t-245 -163t-298 -60.5q-157 0 -299.5 61t-245.5 164t-163.5 244.5t-60.5 297.5zM171 765q0 -242 178 -422q177 -177 422 -177q162 0 300 80.5 t219 218.5t81 300t-81 300.5t-219 219t-300 80.5t-300 -80.5t-219 -219t-81 -300.5zM505 507l256 600q2 11 10 11q9 0 11 -11l255 -600q4 -11 -2 -17t-17 0l-236 89q-10 5 -21 0l-239 -89q-10 -6 -16 0t-1 17z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M8.5 572q-53.5 200 0.5 397q22 82 63.5 161t108 154.5t149.5 132t194 91t234 34.5q318 0 544 -228q148 -148 201.5 -346t0.5 -397q-22 -82 -63.5 -161t-108 -154.5t-148.5 -132t-192.5 -91t-233.5 -34.5q-322 0 -547 226q-149 148 -202.5 348zM155 770q0 -250 176 -426 t427 -176q162 0 300.5 80.5t219 219t80.5 302.5q0 122 -47.5 233t-128 191.5t-191.5 128t-233 47.5q-164 0 -303 -80.5t-219.5 -219t-80.5 -300.5zM375 777q0 10 10 14l231 104q10 5 15 15l103 229q9 12 16 12q8 0 11 -12l248 -605q2 -11 -2 -15t-16 -2l-606 248 q-10 3 -10 12z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M30.5 573q-53.5 200 0.5 397q22 82 63.5 161t107.5 154t148.5 131.5t193.5 91t234 34.5q318 0 543 -228q149 -147 202.5 -345.5t-0.5 -395.5q-22 -82 -63 -161.5t-107.5 -154.5t-148.5 -132t-192.5 -91.5t-233.5 -34.5q-322 0 -545 227q-149 147 -202.5 347zM176 771 q0 -249 176 -426q175 -175 426 -175q162 0 300 80t218.5 218.5t80.5 302.5q0 162 -80.5 300.5t-218.5 219t-300 80.5q-164 0 -302.5 -80.5t-219 -219t-80.5 -300.5zM525 536l250 605q1 10 10 10q10 0 14 -10l104 -231q2 -9 16 -14l230 -104q11 -4 11 -14q0 -9 -11 -12 l-605 -248q-10 -4 -15 1t-4 17z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M6 766q0 156 61.5 298.5t164.5 245.5t245 163.5t298 60.5t298.5 -60.5t245.5 -163.5t164 -245t61 -299t-61 -299t-164 -244.5t-245.5 -163t-298.5 -60.5t-298.5 61t-245.5 164t-164 245t-61 297zM176 766q0 -245 177 -422q176 -176 422 -176q163 0 301.5 80.5t219 218 t80.5 299.5q0 121 -47.5 232t-128.5 191.5t-192 128t-233 47.5q-121 0 -231.5 -47.5t-191 -128t-128.5 -191.5t-48 -232zM510 1025q-5 11 1 16.5t16 0.5l238 -89q10 -4 22 0l236 89q10 5 16 -0.5t2 -16.5l-254 -599q-3 -10 -12 -10q-7 0 -10 10z" />
|
||||
<glyph unicode="" horiz-adv-x="1542" d="M6 769q0 157 61.5 300t165 246.5t246 164.5t298.5 61t298.5 -61t246 -164.5t164.5 -246.5t61 -300t-61 -300t-164.5 -245.5t-246 -163.5t-298.5 -61q-157 0 -300 61t-246 164.5t-164 246t-61 298.5zM176 769q0 -246 178 -424q177 -177 423 -177q163 0 301.5 81 t219.5 219.5t81 300.5t-81 300.5t-219.5 219.5t-301.5 81q-162 0 -300.5 -81t-219.5 -219.5t-81 -300.5zM424 769q0 9 11 10l602 258q11 5 16.5 -1.5t0.5 -16.5l-89 -240q-7 -10 0 -20l89 -238q5 -10 -0.5 -16t-16.5 -1l-602 255q-11 1 -11 10z" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
Before Width: | Height: | Size: 94 KiB |
Binary file not shown.
Binary file not shown.
26
fonts/package-lock.json
generated
Normal file
26
fonts/package-lock.json
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "magicmirror-fonts",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "magicmirror-fonts",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"roboto-fontface": "^0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/roboto-fontface": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz",
|
||||
"integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"roboto-fontface": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz",
|
||||
"integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g=="
|
||||
}
|
||||
}
|
||||
}
|
||||
15
fonts/package.json
Normal file
15
fonts/package.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "magicmirror-fonts",
|
||||
"description": "Package for fonts use by MagicMirror Core.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/MichMich/MagicMirror.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MichMich/MagicMirror/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"roboto-fontface": "^0.10.0"
|
||||
}
|
||||
}
|
||||
58
fonts/roboto.css
Normal file
58
fonts/roboto.css
Normal file
@@ -0,0 +1,58 @@
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local("Roboto Thin"), local("Roboto-Thin"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto Condensed";
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Light.woff2") format("woff2"),
|
||||
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Light.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto Condensed";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Regular.woff2") format("woff2"),
|
||||
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Regular.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto Condensed";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Bold.woff2") format("woff2"),
|
||||
url("node_modules/roboto-fontface/fonts/roboto-condensed/Roboto-Condensed-Bold.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Roboto"), local("Roboto-Regular"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Regular.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local("Roboto Medium"), local("Roboto-Medium"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Medium.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local("Roboto Bold"), local("Roboto-Bold"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Bold.woff") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local("Roboto Light"), local("Roboto-Light"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff2") format("woff2"), url("node_modules/roboto-fontface/fonts/roboto/Roboto-Light.woff") format("woff");
|
||||
}
|
||||
57
index.html
Normal file
57
index.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>MagicMirror²</title>
|
||||
<meta name="google" content="notranslate" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
|
||||
<link rel="icon" href="data:;base64,iVBORw0KGgo=" />
|
||||
<link rel="stylesheet" type="text/css" href="css/main.css" />
|
||||
<link rel="stylesheet" type="text/css" href="fonts/roboto.css" />
|
||||
<!-- custom.css is loaded by the loader.js to make sure it's loaded after the module css files. -->
|
||||
|
||||
<script type="text/javascript">
|
||||
window.mmVersion = "#VERSION#";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="region fullscreen below"><div class="container"></div></div>
|
||||
<div class="region top bar">
|
||||
<div class="container"></div>
|
||||
<div class="region top left"><div class="container"></div></div>
|
||||
<div class="region top center"><div class="container"></div></div>
|
||||
<div class="region top right"><div class="container"></div></div>
|
||||
</div>
|
||||
<div class="region upper third"><div class="container"></div></div>
|
||||
<div class="region middle center"><div class="container"></div></div>
|
||||
<div class="region lower third">
|
||||
<div class="container"><br /></div>
|
||||
</div>
|
||||
<div class="region bottom bar">
|
||||
<div class="container"></div>
|
||||
<div class="region bottom left"><div class="container"></div></div>
|
||||
<div class="region bottom center"><div class="container"></div></div>
|
||||
<div class="region bottom right"><div class="container"></div></div>
|
||||
</div>
|
||||
<div class="region fullscreen above"><div class="container"></div></div>
|
||||
<script type="text/javascript" src="socket.io/socket.io.js"></script>
|
||||
<script type="text/javascript" src="vendor/node_modules/nunjucks/browser/nunjucks.min.js"></script>
|
||||
<script type="text/javascript" src="js/defaults.js"></script>
|
||||
<script type="text/javascript" src="#CONFIG_FILE#"></script>
|
||||
<script type="text/javascript" src="vendor/vendor.js"></script>
|
||||
<script type="text/javascript" src="modules/default/defaultmodules.js"></script>
|
||||
<script type="text/javascript" src="js/logger.js"></script>
|
||||
<script type="text/javascript" src="translations/translations.js"></script>
|
||||
<script type="text/javascript" src="js/translator.js"></script>
|
||||
<script type="text/javascript" src="js/class.js"></script>
|
||||
<script type="text/javascript" src="js/module.js"></script>
|
||||
<script type="text/javascript" src="js/loader.js"></script>
|
||||
<script type="text/javascript" src="js/socketclient.js"></script>
|
||||
<script type="text/javascript" src="js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
39
index.php
39
index.php
@@ -1,39 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Magic Mirror</title>
|
||||
<style type="text/css">
|
||||
<?php include('css/main.css') ?>
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="css/weather-icons.css">
|
||||
<script type="text/javascript">
|
||||
var gitHash = '<?php echo trim(`git rev-parse HEAD`) ?>';
|
||||
</script>
|
||||
<meta name="google" value="notranslate" />
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="top left"><div class="date small dimmed"></div><div class="time"></div><div class="calendar xxsmall"></div></div>
|
||||
<div class="top right"><div class="windsun small dimmed"></div><div class="temp"></div><div class="forecast small dimmed"></div></div>
|
||||
<div class="center-ver center-hor"><!-- <div class="dishwasher light">Vaatwasser is klaar!</div> --></div>
|
||||
<div class="lower-third center-hor"><div class="compliment light"></div></div>
|
||||
<div class="bottom center-hor"><div class="news medium"></div></div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="js/jquery.js"></script>
|
||||
<script src="js/jquery.feedToJSON.js"></script>
|
||||
<script src="js/ical_parser.js"></script>
|
||||
<script src="js/moment-with-locales.min.js"></script>
|
||||
<script src="js/config.js"></script>
|
||||
<script src="js/rrule.js"></script>
|
||||
<script src="js/version/version.js"></script>
|
||||
<script src="js/calendar/calendar.js"></script>
|
||||
<script src="js/compliments/compliments.js"></script>
|
||||
<script src="js/weather/weather.js"></script>
|
||||
<script src="js/time/time.js"></script>
|
||||
<script src="js/news/news.js"></script>
|
||||
<script src="js/main.js?nocache=<?php echo md5(microtime()) ?>"></script>
|
||||
<!-- <script src="js/socket.io.min.js"></script> -->
|
||||
</body>
|
||||
</html>
|
||||
3
installers/mm.sh
Executable file
3
installers/mm.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
# This file is still here to keep PM2 working on older installations.
|
||||
cd ~/MagicMirror
|
||||
DISPLAY=:0 npm start
|
||||
290
js/app.js
Normal file
290
js/app.js
Normal file
@@ -0,0 +1,290 @@
|
||||
/* Magic Mirror
|
||||
* The Core App (Server)
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
|
||||
// Alias modules mentioned in package.js under _moduleAliases.
|
||||
require("module-alias/register");
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const Log = require("logger");
|
||||
const Server = require(`${__dirname}/server`);
|
||||
const Utils = require(`${__dirname}/utils`);
|
||||
const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`);
|
||||
|
||||
// Get version number.
|
||||
global.version = require(`${__dirname}/../package.json`).version;
|
||||
Log.log("Starting MagicMirror: v" + global.version);
|
||||
|
||||
// global absolute root path
|
||||
global.root_path = path.resolve(`${__dirname}/../`);
|
||||
|
||||
if (process.env.MM_CONFIG_FILE) {
|
||||
global.configuration_file = process.env.MM_CONFIG_FILE;
|
||||
}
|
||||
|
||||
// FIXME: Hotfix Pull Request
|
||||
// https://github.com/MichMich/MagicMirror/pull/673
|
||||
if (process.env.MM_PORT) {
|
||||
global.mmPort = process.env.MM_PORT;
|
||||
}
|
||||
|
||||
// The next part is here to prevent a major exception when there
|
||||
// is no internet connection. This could probable be solved better.
|
||||
process.on("uncaughtException", function (err) {
|
||||
Log.error("Whoops! There was an uncaught exception...");
|
||||
Log.error(err);
|
||||
Log.error("MagicMirror will not quit, but it might be a good idea to check why this happened. Maybe no internet connection?");
|
||||
Log.error("If you think this really is an issue, please open an issue on GitHub: https://github.com/MichMich/MagicMirror/issues");
|
||||
});
|
||||
|
||||
/**
|
||||
* The core app.
|
||||
*
|
||||
* @class
|
||||
*/
|
||||
function App() {
|
||||
let nodeHelpers = [];
|
||||
let httpServer;
|
||||
|
||||
/**
|
||||
* Loads the config file. Combines it with the defaults, and runs the
|
||||
* callback with the found config as argument.
|
||||
*
|
||||
* @param {Function} callback Function to be called after loading the config
|
||||
*/
|
||||
function loadConfig(callback) {
|
||||
Log.log("Loading config ...");
|
||||
const defaults = require(`${__dirname}/defaults`);
|
||||
|
||||
// For this check proposed to TestSuite
|
||||
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
|
||||
const configFilename = path.resolve(global.configuration_file || `${global.root_path}/config/config.js`);
|
||||
|
||||
try {
|
||||
fs.accessSync(configFilename, fs.F_OK);
|
||||
const c = require(configFilename);
|
||||
checkDeprecatedOptions(c);
|
||||
const config = Object.assign(defaults, c);
|
||||
callback(config);
|
||||
} catch (e) {
|
||||
if (e.code === "ENOENT") {
|
||||
Log.error(Utils.colors.error("WARNING! Could not find config file. Please create one. Starting with default configuration."));
|
||||
} else if (e instanceof ReferenceError || e instanceof SyntaxError) {
|
||||
Log.error(Utils.colors.error(`WARNING! Could not validate config file. Starting with default configuration. Please correct syntax errors at or above this line: ${e.stack}`));
|
||||
} else {
|
||||
Log.error(Utils.colors.error(`WARNING! Could not load config file. Starting with default configuration. Error found: ${e}`));
|
||||
}
|
||||
callback(defaults);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the config for deprecated options and throws a warning in the logs
|
||||
* if it encounters one option from the deprecated.js list
|
||||
*
|
||||
* @param {object} userConfig The user config
|
||||
*/
|
||||
function checkDeprecatedOptions(userConfig) {
|
||||
const deprecated = require(`${global.root_path}/js/deprecated`);
|
||||
const deprecatedOptions = deprecated.configs;
|
||||
|
||||
const usedDeprecated = deprecatedOptions.filter((option) => userConfig.hasOwnProperty(option));
|
||||
if (usedDeprecated.length > 0) {
|
||||
Log.warn(Utils.colors.warn(`WARNING! Your config is using deprecated options: ${usedDeprecated.join(", ")}. Check README and CHANGELOG for more up-to-date ways of getting the same functionality.`));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a specific module.
|
||||
*
|
||||
* @param {string} module The name of the module (including subpath).
|
||||
* @param {Function} callback Function to be called after loading
|
||||
*/
|
||||
function loadModule(module, callback) {
|
||||
const elements = module.split("/");
|
||||
const moduleName = elements[elements.length - 1];
|
||||
let moduleFolder = `${__dirname}/../modules/${module}`;
|
||||
|
||||
if (defaultModules.includes(moduleName)) {
|
||||
moduleFolder = `${__dirname}/../modules/default/${module}`;
|
||||
}
|
||||
|
||||
const helperPath = `${moduleFolder}/node_helper.js`;
|
||||
|
||||
let loadHelper = true;
|
||||
try {
|
||||
fs.accessSync(helperPath, fs.R_OK);
|
||||
} catch (e) {
|
||||
loadHelper = false;
|
||||
Log.log(`No helper found for module: ${moduleName}.`);
|
||||
}
|
||||
|
||||
if (loadHelper) {
|
||||
const Module = require(helperPath);
|
||||
let m = new Module();
|
||||
|
||||
if (m.requiresVersion) {
|
||||
Log.log(`Check MagicMirror version for node helper '${moduleName}' - Minimum version: ${m.requiresVersion} - Current version: ${global.version}`);
|
||||
if (cmpVersions(global.version, m.requiresVersion) >= 0) {
|
||||
Log.log("Version is ok!");
|
||||
} else {
|
||||
Log.warn(`Version is incorrect. Skip module: '${moduleName}'`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m.setName(moduleName);
|
||||
m.setPath(path.resolve(moduleFolder));
|
||||
nodeHelpers.push(m);
|
||||
|
||||
m.loaded(callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all modules.
|
||||
*
|
||||
* @param {Module[]} modules All modules to be loaded
|
||||
* @param {Function} callback Function to be called after loading
|
||||
*/
|
||||
function loadModules(modules, callback) {
|
||||
Log.log("Loading module helpers ...");
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function loadNextModule() {
|
||||
if (modules.length > 0) {
|
||||
const nextModule = modules[0];
|
||||
loadModule(nextModule, function () {
|
||||
modules = modules.slice(1);
|
||||
loadNextModule();
|
||||
});
|
||||
} else {
|
||||
// All modules are loaded
|
||||
Log.log("All module helpers loaded.");
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
loadNextModule();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two semantic version numbers and return the difference.
|
||||
*
|
||||
* @param {string} a Version number a.
|
||||
* @param {string} b Version number b.
|
||||
* @returns {number} A positive number if a is larger than b, a negative
|
||||
* number if a is smaller and 0 if they are the same
|
||||
*/
|
||||
function cmpVersions(a, b) {
|
||||
let i, diff;
|
||||
const regExStrip0 = /(\.0+)+$/;
|
||||
const segmentsA = a.replace(regExStrip0, "").split(".");
|
||||
const segmentsB = b.replace(regExStrip0, "").split(".");
|
||||
const l = Math.min(segmentsA.length, segmentsB.length);
|
||||
|
||||
for (i = 0; i < l; i++) {
|
||||
diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
|
||||
if (diff) {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
return segmentsA.length - segmentsB.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the core app.
|
||||
*
|
||||
* It loads the config, then it loads all modules. When it's done it
|
||||
* executes the callback with the config as argument.
|
||||
*
|
||||
* @param {Function} callback Function to be called after start
|
||||
*/
|
||||
this.start = function (callback) {
|
||||
loadConfig(function (c) {
|
||||
config = c;
|
||||
|
||||
Log.setLogLevel(config.logLevel);
|
||||
|
||||
let modules = [];
|
||||
|
||||
for (const module of config.modules) {
|
||||
if (!modules.includes(module.module) && !module.disabled) {
|
||||
modules.push(module.module);
|
||||
}
|
||||
}
|
||||
|
||||
loadModules(modules, function () {
|
||||
httpServer = new Server(config, function (app, io) {
|
||||
Log.log("Server started ...");
|
||||
|
||||
for (let nodeHelper of nodeHelpers) {
|
||||
nodeHelper.setExpressApp(app);
|
||||
nodeHelper.setSocketIO(io);
|
||||
nodeHelper.start();
|
||||
}
|
||||
|
||||
Log.log("Sockets connected & modules started ...");
|
||||
|
||||
if (typeof callback === "function") {
|
||||
callback(config);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops the core app. This calls each node_helper's STOP() function, if it
|
||||
* exists.
|
||||
*
|
||||
* Added to fix #1056
|
||||
*/
|
||||
this.stop = function () {
|
||||
for (const nodeHelper of nodeHelpers) {
|
||||
if (typeof nodeHelper.stop === "function") {
|
||||
nodeHelper.stop();
|
||||
}
|
||||
}
|
||||
httpServer.close();
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for SIGINT signal and call stop() function.
|
||||
*
|
||||
* Added to fix #1056
|
||||
* Note: this is only used if running `server-only`. Otherwise
|
||||
* this.stop() is called by app.on("before-quit"... in `electron.js`
|
||||
*/
|
||||
process.on("SIGINT", () => {
|
||||
Log.log("[SIGINT] Received. Shutting down server...");
|
||||
setTimeout(() => {
|
||||
process.exit(0);
|
||||
}, 3000); // Force quit after 3 seconds
|
||||
this.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
/**
|
||||
* Listen to SIGTERM signals so we can stop everything when we
|
||||
* are asked to stop by the OS.
|
||||
*/
|
||||
process.on("SIGTERM", () => {
|
||||
Log.log("[SIGTERM] Received. Shutting down server...");
|
||||
setTimeout(() => {
|
||||
process.exit(0);
|
||||
}, 3000); // Force quit after 3 seconds
|
||||
this.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = new App();
|
||||
@@ -1,139 +0,0 @@
|
||||
var calendar = {
|
||||
eventList: [],
|
||||
calendarLocation: '.calendar',
|
||||
updateInterval: 1000,
|
||||
updateDataInterval: 60000,
|
||||
fadeInterval: 1000,
|
||||
intervalId: null,
|
||||
dataIntervalId: null,
|
||||
maximumEntries: config.calendar.maximumEntries || 10
|
||||
}
|
||||
|
||||
calendar.updateData = function (callback) {
|
||||
|
||||
new ical_parser("controllers/calendar.php" + "?url="+encodeURIComponent(config.calendar.url), function(cal) {
|
||||
var events = cal.getEvents();
|
||||
this.eventList = [];
|
||||
|
||||
for (var i in events) {
|
||||
|
||||
var e = events[i];
|
||||
for (var key in e) {
|
||||
var value = e[key];
|
||||
var seperator = key.search(';');
|
||||
if (seperator >= 0) {
|
||||
var mainKey = key.substring(0,seperator);
|
||||
var subKey = key.substring(seperator+1);
|
||||
|
||||
var dt;
|
||||
if (subKey == 'VALUE=DATE') {
|
||||
//date
|
||||
dt = new Date(value.substring(0,4), value.substring(4,6) - 1, value.substring(6,8));
|
||||
} else {
|
||||
//time
|
||||
dt = new Date(value.substring(0,4), value.substring(4,6) - 1, value.substring(6,8), value.substring(9,11), value.substring(11,13), value.substring(13,15));
|
||||
}
|
||||
|
||||
if (mainKey == 'DTSTART') e.startDate = dt;
|
||||
if (mainKey == 'DTEND') e.endDate = dt;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.startDate == undefined){
|
||||
//some old events in Gmail Calendar is "start_date"
|
||||
//FIXME: problems with Gmail's TimeZone
|
||||
var days = moment(e.DTSTART).diff(moment(), 'days');
|
||||
var seconds = moment(e.DTSTART).diff(moment(), 'seconds');
|
||||
var startDate = moment(e.DTSTART);
|
||||
} else {
|
||||
var days = moment(e.startDate).diff(moment(), 'days');
|
||||
var seconds = moment(e.startDate).diff(moment(), 'seconds');
|
||||
var startDate = moment(e.startDate);
|
||||
}
|
||||
|
||||
//only add fututre events, days doesn't work, we need to check seconds
|
||||
if (seconds >= 0) {
|
||||
if (seconds <= 60*60*5 || seconds >= 60*60*24*2) {
|
||||
var time_string = moment(startDate).fromNow();
|
||||
}else {
|
||||
var time_string = moment(startDate).calendar()
|
||||
}
|
||||
if (!e.RRULE) {
|
||||
this.eventList.push({'description':e.SUMMARY,'seconds':seconds,'days':time_string});
|
||||
}
|
||||
e.seconds = seconds;
|
||||
}
|
||||
|
||||
// Special handling for rrule events
|
||||
if (e.RRULE) {
|
||||
var options = new RRule.parseString(e.RRULE);
|
||||
options.dtstart = e.startDate;
|
||||
var rule = new RRule(options);
|
||||
|
||||
var oneYear = new Date();
|
||||
oneYear.setFullYear(oneYear.getFullYear() + 1);
|
||||
|
||||
var dates = rule.between(new Date(), oneYear, true, function (date, i){return i < 10});
|
||||
for (date in dates) {
|
||||
var dt = new Date(dates[date]);
|
||||
var days = moment(dt).diff(moment(), 'days');
|
||||
var seconds = moment(dt).diff(moment(), 'seconds');
|
||||
var startDate = moment(dt);
|
||||
if (seconds >= 0) {
|
||||
if (seconds <= 60*60*5 || seconds >= 60*60*24*2) {
|
||||
var time_string = moment(dt).fromNow();
|
||||
} else {
|
||||
var time_string = moment(dt).calendar()
|
||||
}
|
||||
this.eventList.push({'description':e.SUMMARY,'seconds':seconds,'days':time_string});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.eventList = this.eventList.sort(function(a,b){return a.seconds-b.seconds});
|
||||
|
||||
// Limit the number of entries.
|
||||
this.eventList = this.eventList.slice(0, calendar.maximumEntries);
|
||||
|
||||
if (callback !== undefined && Object.prototype.toString.call(callback) === '[object Function]') {
|
||||
callback(this.eventList);
|
||||
}
|
||||
|
||||
}.bind(this));
|
||||
|
||||
}
|
||||
|
||||
calendar.updateCalendar = function (eventList) {
|
||||
|
||||
table = $('<table/>').addClass('xsmall').addClass('calendar-table');
|
||||
opacity = 1;
|
||||
|
||||
for (var i in eventList) {
|
||||
var e = eventList[i];
|
||||
|
||||
var row = $('<tr/>').css('opacity',opacity);
|
||||
row.append($('<td/>').html(e.description).addClass('description'));
|
||||
row.append($('<td/>').html(e.days).addClass('days dimmed'));
|
||||
table.append(row);
|
||||
|
||||
opacity -= 1 / eventList.length;
|
||||
}
|
||||
|
||||
$(this.calendarLocation).updateWithText(table, this.fadeInterval);
|
||||
|
||||
}
|
||||
|
||||
calendar.init = function () {
|
||||
|
||||
this.updateData(this.updateCalendar.bind(this));
|
||||
|
||||
this.intervalId = setInterval(function () {
|
||||
this.updateCalendar(this.eventList)
|
||||
}.bind(this), this.updateInterval);
|
||||
|
||||
this.dataIntervalId = setInterval(function () {
|
||||
this.updateData(this.updateCalendar.bind(this));
|
||||
}.bind(this), this.updateDataInterval);
|
||||
|
||||
}
|
||||
73
js/check_config.js
Normal file
73
js/check_config.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/* Magic Mirror
|
||||
*
|
||||
* Check the configuration file for errors
|
||||
*
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const Linter = require("eslint").Linter;
|
||||
const linter = new Linter();
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const rootPath = path.resolve(`${__dirname}/../`);
|
||||
const Log = require(`${rootPath}/js/logger.js`);
|
||||
const Utils = require(`${rootPath}/js/utils.js`);
|
||||
|
||||
/**
|
||||
* Returns a string with path of configuration file.
|
||||
* Check if set by environment variable MM_CONFIG_FILE
|
||||
*
|
||||
* @returns {string} path and filename of the config file
|
||||
*/
|
||||
function getConfigFile() {
|
||||
// FIXME: This function should be in core. Do you want refactor me ;) ?, be good!
|
||||
return path.resolve(process.env.MM_CONFIG_FILE || `${rootPath}/config/config.js`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the config file using eslint.
|
||||
*/
|
||||
function checkConfigFile() {
|
||||
const configFileName = getConfigFile();
|
||||
|
||||
// Check if file is present
|
||||
if (fs.existsSync(configFileName) === false) {
|
||||
Log.error(Utils.colors.error("File not found: "), configFileName);
|
||||
throw new Error("No config file present!");
|
||||
}
|
||||
|
||||
// Check permission
|
||||
try {
|
||||
fs.accessSync(configFileName, fs.F_OK);
|
||||
} catch (e) {
|
||||
Log.error(Utils.colors.error(e));
|
||||
throw new Error("No permission to access config file!");
|
||||
}
|
||||
|
||||
// Validate syntax of the configuration file.
|
||||
Log.info(Utils.colors.info("Checking file... "), configFileName);
|
||||
|
||||
// I'm not sure if all ever is utf-8
|
||||
const configFile = fs.readFileSync(configFileName, "utf-8");
|
||||
|
||||
// Explicitly tell linter that he might encounter es6 syntax ("let config = {...}")
|
||||
const errors = linter.verify(configFile, {
|
||||
env: {
|
||||
es6: true
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length === 0) {
|
||||
Log.info(Utils.colors.pass("Your configuration file doesn't contain syntax errors :)"));
|
||||
} else {
|
||||
Log.error(Utils.colors.error("Your configuration file contains syntax errors :("));
|
||||
|
||||
for (const error of errors) {
|
||||
Log.error(`Line ${error.line} column ${error.column}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkConfigFile();
|
||||
109
js/class.js
Normal file
109
js/class.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/* global Class, xyz */
|
||||
|
||||
/* Simple JavaScript Inheritance
|
||||
* By John Resig https://johnresig.com/
|
||||
*
|
||||
* Inspired by base2 and Prototype
|
||||
*
|
||||
* MIT Licensed.
|
||||
*/
|
||||
(function () {
|
||||
let initializing = false;
|
||||
const fnTest = /xyz/.test(function () {
|
||||
xyz;
|
||||
})
|
||||
? /\b_super\b/
|
||||
: /.*/;
|
||||
|
||||
// The base Class implementation (does nothing)
|
||||
this.Class = function () {};
|
||||
|
||||
// Create a new Class that inherits from this class
|
||||
Class.extend = function (prop) {
|
||||
let _super = this.prototype;
|
||||
|
||||
// Instantiate a base class (but only create the instance,
|
||||
// don't run the init constructor)
|
||||
initializing = true;
|
||||
const prototype = new this();
|
||||
initializing = false;
|
||||
|
||||
// Make a copy of all prototype properties, to prevent reference issues.
|
||||
for (const p in prototype) {
|
||||
prototype[p] = cloneObject(prototype[p]);
|
||||
}
|
||||
|
||||
// Copy the properties over onto the new prototype
|
||||
for (const name in prop) {
|
||||
// Check if we're overwriting an existing function
|
||||
prototype[name] =
|
||||
typeof prop[name] === "function" && typeof _super[name] === "function" && fnTest.test(prop[name])
|
||||
? (function (name, fn) {
|
||||
return function () {
|
||||
const tmp = this._super;
|
||||
|
||||
// Add a new ._super() method that is the same method
|
||||
// but on the super-class
|
||||
this._super = _super[name];
|
||||
|
||||
// The method only need to be bound temporarily, so we
|
||||
// remove it when we're done executing
|
||||
const ret = fn.apply(this, arguments);
|
||||
this._super = tmp;
|
||||
|
||||
return ret;
|
||||
};
|
||||
})(name, prop[name])
|
||||
: prop[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* The dummy class constructor
|
||||
*/
|
||||
function Class() {
|
||||
// All construction is actually done in the init method
|
||||
if (!initializing && this.init) {
|
||||
this.init.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
// Populate our constructed prototype object
|
||||
Class.prototype = prototype;
|
||||
|
||||
// Enforce the constructor to be what we expect
|
||||
Class.prototype.constructor = Class;
|
||||
|
||||
// And make this class extendable
|
||||
Class.extend = arguments.callee;
|
||||
|
||||
return Class;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Define the clone method for later use. Helper Method.
|
||||
*
|
||||
* @param {object} obj Object to be cloned
|
||||
* @returns {object} the cloned object
|
||||
*/
|
||||
function cloneObject(obj) {
|
||||
if (obj === null || typeof obj !== "object") {
|
||||
return obj;
|
||||
}
|
||||
|
||||
const temp = obj.constructor(); // give temp the original obj's constructor
|
||||
for (const key in obj) {
|
||||
temp[key] = cloneObject(obj[key]);
|
||||
|
||||
if (key === "lockStrings") {
|
||||
Log.log(key);
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = Class;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
var compliments = {
|
||||
complimentLocation: '.compliment',
|
||||
currentCompliment: '',
|
||||
complimentList: {
|
||||
'morning': config.compliments.morning,
|
||||
'afternoon': config.compliments.afternoon,
|
||||
'evening': config.compliments.evening
|
||||
},
|
||||
updateInterval: config.compliments.interval || 30000,
|
||||
fadeInterval: config.compliments.fadeInterval || 4000,
|
||||
intervalId: null
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the compliment visible on the screen
|
||||
*/
|
||||
compliments.updateCompliment = function () {
|
||||
|
||||
|
||||
|
||||
var _list = [];
|
||||
|
||||
var hour = moment().hour();
|
||||
|
||||
// In the followign if statement we use .slice() on the
|
||||
// compliments array to make a copy by value.
|
||||
// This way the original array of compliments stays in tact.
|
||||
|
||||
if (hour >= 3 && hour < 12) {
|
||||
// Morning compliments
|
||||
_list = compliments.complimentList['morning'].slice();
|
||||
} else if (hour >= 12 && hour < 17) {
|
||||
// Afternoon compliments
|
||||
_list = compliments.complimentList['afternoon'].slice();
|
||||
} else if (hour >= 17 || hour < 3) {
|
||||
// Evening compliments
|
||||
_list = compliments.complimentList['evening'].slice();
|
||||
} else {
|
||||
// Edge case in case something weird happens
|
||||
// This will select a compliment from all times of day
|
||||
Object.keys(compliments.complimentList).forEach(function (_curr) {
|
||||
_list = _list.concat(compliments.complimentList[_curr]).slice();
|
||||
});
|
||||
}
|
||||
|
||||
// Search for the location of the current compliment in the list
|
||||
var _spliceIndex = _list.indexOf(compliments.currentCompliment);
|
||||
|
||||
// If it exists, remove it so we don't see it again
|
||||
if (_spliceIndex !== -1) {
|
||||
_list.splice(_spliceIndex, 1);
|
||||
}
|
||||
|
||||
// Randomly select a location
|
||||
var _randomIndex = Math.floor(Math.random() * _list.length);
|
||||
compliments.currentCompliment = _list[_randomIndex];
|
||||
|
||||
$('.compliment').updateWithText(compliments.currentCompliment, compliments.fadeInterval);
|
||||
|
||||
}
|
||||
|
||||
compliments.init = function () {
|
||||
|
||||
this.updateCompliment();
|
||||
|
||||
this.intervalId = setInterval(function () {
|
||||
this.updateCompliment();
|
||||
}.bind(this), this.updateInterval)
|
||||
|
||||
}
|
||||
43
js/config.js
43
js/config.js
@@ -1,43 +0,0 @@
|
||||
var config = {
|
||||
lang: 'nl',
|
||||
time: {
|
||||
timeFormat: 12
|
||||
},
|
||||
weather: {
|
||||
//change weather params here:
|
||||
//units: metric or imperial
|
||||
params: {
|
||||
q: 'Baarn,Netherlands',
|
||||
units: 'metric',
|
||||
// if you want a different lang for the weather that what is set above, change it here
|
||||
lang: 'nl',
|
||||
APPID: 'YOUR_FREE_OPENWEATHER_API_KEY'
|
||||
}
|
||||
},
|
||||
compliments: {
|
||||
interval: 30000,
|
||||
fadeInterval: 4000,
|
||||
morning: [
|
||||
'Good morning, handsome!',
|
||||
'Enjoy your day!',
|
||||
'How was your sleep?'
|
||||
],
|
||||
afternoon: [
|
||||
'Hello, beauty!',
|
||||
'You look sexy!',
|
||||
'Looking good today!'
|
||||
],
|
||||
evening: [
|
||||
'Wow, you look hot!',
|
||||
'You look nice!',
|
||||
'Hi, sexy!'
|
||||
]
|
||||
},
|
||||
calendar: {
|
||||
maximumEntries: 10,
|
||||
url: "https://p01-calendarws.icloud.com/ca/subscribe/1/n6x7Farxpt7m9S8bHg1TGArSj7J6kanm_2KEoJPL5YIAk3y70FpRo4GyWwO-6QfHSY5mXtHcRGVxYZUf7U3HPDOTG5x0qYnno1Zr_VuKH2M"
|
||||
},
|
||||
news: {
|
||||
feed: 'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'
|
||||
}
|
||||
}
|
||||
84
js/defaults.js
Normal file
84
js/defaults.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/* global mmPort */
|
||||
|
||||
/* Magic Mirror
|
||||
* Config Defaults
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const address = "localhost";
|
||||
let port = 8080;
|
||||
if (typeof mmPort !== "undefined") {
|
||||
port = mmPort;
|
||||
}
|
||||
const defaults = {
|
||||
address: address,
|
||||
port: port,
|
||||
basePath: "/",
|
||||
kioskmode: false,
|
||||
electronOptions: {},
|
||||
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
|
||||
|
||||
language: "en",
|
||||
logLevel: ["INFO", "LOG", "WARN", "ERROR"],
|
||||
timeFormat: 24,
|
||||
units: "metric",
|
||||
zoom: 1,
|
||||
customCss: "css/custom.css",
|
||||
|
||||
modules: [
|
||||
{
|
||||
module: "updatenotification",
|
||||
position: "top_center"
|
||||
},
|
||||
{
|
||||
module: "helloworld",
|
||||
position: "upper_third",
|
||||
classes: "large thin",
|
||||
config: {
|
||||
text: "Magic Mirror<sup>2</sup>"
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "helloworld",
|
||||
position: "middle_center",
|
||||
config: {
|
||||
text: "Please create a config file or check the existing one for errors."
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "helloworld",
|
||||
position: "middle_center",
|
||||
classes: "small dimmed",
|
||||
config: {
|
||||
text: "See README for more information."
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "helloworld",
|
||||
position: "middle_center",
|
||||
classes: "xsmall",
|
||||
config: {
|
||||
text: "If you get this message while your config file is already created,<br>" + "it probably contains an error. To validate your config file run in your MagicMirror directory<br>" + "<pre>npm run config:check</pre>"
|
||||
}
|
||||
},
|
||||
{
|
||||
module: "helloworld",
|
||||
position: "bottom_bar",
|
||||
classes: "xsmall dimmed",
|
||||
config: {
|
||||
text: "www.michaelteeuw.nl"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
paths: {
|
||||
modules: "modules",
|
||||
vendor: "vendor"
|
||||
}
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = defaults;
|
||||
}
|
||||
11
js/deprecated.js
Normal file
11
js/deprecated.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Magic Mirror Deprecated Config Options List
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*
|
||||
* Olex S. original idea this deprecated option
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
configs: ["kioskmode"]
|
||||
};
|
||||
149
js/electron.js
Normal file
149
js/electron.js
Normal file
@@ -0,0 +1,149 @@
|
||||
"use strict";
|
||||
|
||||
const electron = require("electron");
|
||||
const core = require("./app.js");
|
||||
const Log = require("logger");
|
||||
|
||||
// Config
|
||||
let config = process.env.config ? JSON.parse(process.env.config) : {};
|
||||
// Module to control application life.
|
||||
const app = electron.app;
|
||||
// Module to create native browser window.
|
||||
const BrowserWindow = electron.BrowserWindow;
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function createWindow() {
|
||||
let electronSwitchesDefaults = ["autoplay-policy", "no-user-gesture-required"];
|
||||
app.commandLine.appendSwitch(...new Set(electronSwitchesDefaults, config.electronSwitches));
|
||||
let electronOptionsDefaults = {
|
||||
width: 800,
|
||||
height: 600,
|
||||
x: 0,
|
||||
y: 0,
|
||||
darkTheme: true,
|
||||
webPreferences: {
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
zoomFactor: config.zoom
|
||||
},
|
||||
backgroundColor: "#000000"
|
||||
};
|
||||
|
||||
// DEPRECATED: "kioskmode" backwards compatibility, to be removed
|
||||
// settings these options directly instead provides cleaner interface
|
||||
if (config.kioskmode) {
|
||||
electronOptionsDefaults.kiosk = true;
|
||||
} else {
|
||||
electronOptionsDefaults.fullscreen = true;
|
||||
electronOptionsDefaults.autoHideMenuBar = true;
|
||||
}
|
||||
|
||||
const electronOptions = Object.assign({}, electronOptionsDefaults, config.electronOptions);
|
||||
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow(electronOptions);
|
||||
|
||||
// and load the index.html of the app.
|
||||
// If config.address is not defined or is an empty string (listening on all interfaces), connect to localhost
|
||||
|
||||
let prefix;
|
||||
if (config["tls"] !== null && config["tls"]) {
|
||||
prefix = "https://";
|
||||
} else {
|
||||
prefix = "http://";
|
||||
}
|
||||
|
||||
let address = (config.address === void 0) | (config.address === "") ? (config.address = "localhost") : config.address;
|
||||
mainWindow.loadURL(`${prefix}${address}:${config.port}`);
|
||||
|
||||
// Open the DevTools if run with "npm start dev"
|
||||
if (process.argv.includes("dev")) {
|
||||
if (process.env.JEST_WORKER_ID !== undefined) {
|
||||
// if we are running with jest
|
||||
const devtools = new BrowserWindow(electronOptions);
|
||||
mainWindow.webContents.setDevToolsWebContents(devtools.webContents);
|
||||
}
|
||||
mainWindow.webContents.openDevTools();
|
||||
}
|
||||
|
||||
// simulate mouse move to hide black cursor on start
|
||||
mainWindow.webContents.on("dom-ready", (event) => {
|
||||
mainWindow.webContents.sendInputEvent({ type: "mouseMove", x: 0, y: 0 });
|
||||
});
|
||||
|
||||
// Set responders for window events.
|
||||
mainWindow.on("closed", function () {
|
||||
mainWindow = null;
|
||||
});
|
||||
|
||||
if (config.kioskmode) {
|
||||
mainWindow.on("blur", function () {
|
||||
mainWindow.focus();
|
||||
});
|
||||
|
||||
mainWindow.on("leave-full-screen", function () {
|
||||
mainWindow.setFullScreen(true);
|
||||
});
|
||||
|
||||
mainWindow.on("resize", function () {
|
||||
setTimeout(function () {
|
||||
mainWindow.reload();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
app.on("ready", function () {
|
||||
Log.log("Launching application.");
|
||||
createWindow();
|
||||
});
|
||||
|
||||
// Quit when all windows are closed.
|
||||
app.on("window-all-closed", function () {
|
||||
if (process.env.JEST_WORKER_ID !== undefined) {
|
||||
// if we are running with jest
|
||||
app.quit();
|
||||
} else {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
app.on("activate", function () {
|
||||
// On OS X it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
|
||||
/* This method will be called when SIGINT is received and will call
|
||||
* each node_helper's stop function if it exists. Added to fix #1056
|
||||
*
|
||||
* Note: this is only used if running Electron. Otherwise
|
||||
* core.stop() is called by process.on("SIGINT"... in `app.js`
|
||||
*/
|
||||
app.on("before-quit", (event) => {
|
||||
Log.log("Shutting down server...");
|
||||
event.preventDefault();
|
||||
setTimeout(() => {
|
||||
process.exit(0);
|
||||
}, 3000); // Force-quit after 3 seconds.
|
||||
core.stop();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Start the core application if server is run on localhost
|
||||
// This starts all node helpers and starts the webserver.
|
||||
if (["localhost", "127.0.0.1", "::1", "::ffff:127.0.0.1", undefined].includes(config.address)) {
|
||||
core.start(function (c) {
|
||||
config = c;
|
||||
});
|
||||
}
|
||||
@@ -1,224 +0,0 @@
|
||||
/**
|
||||
* Javascript ical Parser
|
||||
* Proof of concept method of reading icalendar (.ics) files with javascript.
|
||||
*
|
||||
* @author: Carl Saggs
|
||||
* @source: https://github.com/thybag/
|
||||
* @version: 0.2
|
||||
*/
|
||||
function ical_parser(feed_url, callback){
|
||||
//store of unproccesed data.
|
||||
this.raw_data = null;
|
||||
//Store of proccessed data.
|
||||
this.events = [];
|
||||
|
||||
/**
|
||||
* loadFile
|
||||
* Using AJAX to load the requested .ics file, passing it to the callback when completed.
|
||||
* @param url URL of .ics file
|
||||
* @param callback Function to call on completion.
|
||||
*/
|
||||
this.loadFile = function(url, callback){
|
||||
//Create request object
|
||||
try {xmlhttp = window.XMLHttpRequest?new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");} catch (e) { }
|
||||
//Grab file
|
||||
xmlhttp.onreadystatechange = function(){
|
||||
if ((xmlhttp.readyState == 4) && (xmlhttp.status == 200)) {
|
||||
//On success, run callback.
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
}
|
||||
xmlhttp.open("GET", url, true);
|
||||
xmlhttp.send(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* makeDate
|
||||
* Convert the dateformat used by ICalendar in to one more suitable for javascript.
|
||||
* @param String ical_date
|
||||
* @return dt object, includes javascript Date + day name, hour/minutes/day/month/year etc.
|
||||
*/
|
||||
this.makeDate = function(ical_date){
|
||||
//break date apart
|
||||
var dtutc = {
|
||||
year: ical_date.substr(0,4),
|
||||
month: ical_date.substr(4,2),
|
||||
day: ical_date.substr(6,2),
|
||||
hour: ical_date.substr(9,2),
|
||||
minute: ical_date.substr(11,2)
|
||||
}
|
||||
//Create JS date (months start at 0 in JS - don't ask)
|
||||
var utcdatems = Date.UTC(dtutc.year, (dtutc.month-1), dtutc.day, dtutc.hour, dtutc.minute);
|
||||
var dt = {};
|
||||
dt.date = new Date(utcdatems);
|
||||
|
||||
dt.year = dt.date.getFullYear();
|
||||
dt.month = ('0' + (dt.date.getMonth()+1)).slice(-2);
|
||||
dt.day = ('0' + dt.date.getDate()).slice(-2);
|
||||
dt.hour = ('0' + dt.date.getHours()).slice(-2);
|
||||
dt.minute = ('0' + dt.date.getMinutes()).slice(-2);
|
||||
|
||||
//Get the full name of the given day
|
||||
dt.dayname =["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"][dt.date.getDay()];
|
||||
dt.monthname = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ][dt.date.getMonth()] ;
|
||||
|
||||
return dt;
|
||||
}
|
||||
|
||||
/**
|
||||
* parseICAL
|
||||
* Convert the ICAL format in to a number of javascript objects (Each representing a date)
|
||||
*
|
||||
* @param data Raw ICAL data
|
||||
*/
|
||||
this.parseICAL = function(data){
|
||||
//Ensure cal is empty
|
||||
this.events = [];
|
||||
|
||||
//Clean string and split the file so we can handle it (line by line)
|
||||
cal_array = data.replace(new RegExp( "\\r", "g" ), "").replace(/\n /g,"").split("\n");
|
||||
|
||||
//Keep track of when we are activly parsing an event
|
||||
var in_event = false;
|
||||
//Use as a holder for the current event being proccessed.
|
||||
var cur_event = null;
|
||||
for(var i=0;i<cal_array.length;i++){
|
||||
ln = cal_array[i];
|
||||
//If we encounted a new Event, create a blank event object + set in event options.
|
||||
if(!in_event && ln == 'BEGIN:VEVENT'){
|
||||
in_event = true;
|
||||
cur_event = {};
|
||||
}
|
||||
//If we encounter end event, complete the object and add it to our events array then clear it for reuse.
|
||||
if(in_event && ln == 'END:VEVENT'){
|
||||
in_event = false;
|
||||
this.events.push(cur_event);
|
||||
cur_event = null;
|
||||
}
|
||||
//If we are in an event
|
||||
else if(in_event){
|
||||
//var lntrim = ln.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
//var lnsplit = lntrim.split(':');
|
||||
//type = lnsplit[0];
|
||||
//val = lnsplit[1];
|
||||
|
||||
//Split the item based on the first ":"
|
||||
idx = ln.indexOf(':');
|
||||
//Apply trimming to values to reduce risks of badly formatted ical files.
|
||||
type = ln.substr(0,idx).replace(/^\s\s*/, '').replace(/\s\s*$/, '');//Trim
|
||||
val = ln.substr(idx+1).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
|
||||
|
||||
//If the type is a start date, proccess it and store details
|
||||
if(type =='DTSTART'){
|
||||
dt = this.makeDate(val);
|
||||
val = dt.date;
|
||||
//These are helpful for display
|
||||
cur_event.start_time = dt.hour+':'+dt.minute;
|
||||
cur_event.start_date = dt.day+'/'+dt.month+'/'+dt.year;
|
||||
cur_event.day = dt.dayname;
|
||||
cur_event.start_date_long = dt.day+'. '+dt.monthname+' '+dt.year ;
|
||||
}
|
||||
//If the type is an end date, do the same as above
|
||||
else if(type =='DTEND'){
|
||||
dt = this.makeDate(val);
|
||||
val = dt.date;
|
||||
//These are helpful for display
|
||||
cur_event.end_time = dt.hour+':'+dt.minute;
|
||||
cur_event.end_date = dt.day+'/'+dt.month+'/'+dt.year;
|
||||
cur_event.day = dt.dayname;
|
||||
}
|
||||
//Convert timestamp
|
||||
else if(type =='DTSTAMP'){
|
||||
val = this.makeDate(val).date;
|
||||
}
|
||||
else {
|
||||
val = val
|
||||
.replace(/\\r\\n/g,'<br />')
|
||||
.replace(/\\n/g,'<br />')
|
||||
.replace(/\\,/g,',');
|
||||
}
|
||||
|
||||
//Add the value to our event object.
|
||||
cur_event[type] = val;
|
||||
}
|
||||
}
|
||||
//Run this to finish proccessing our Events.
|
||||
this.complete();
|
||||
}
|
||||
/**
|
||||
* complete
|
||||
* Sort all events in to a sensible order and run the original callback
|
||||
*/
|
||||
this.complete = function(){
|
||||
//Sort the data so its in date order.
|
||||
this.events.sort(function(a,b){
|
||||
return a.DTSTART-b.DTSTART;
|
||||
});
|
||||
//Run callback method, if was defined. (return self)
|
||||
if(typeof callback == 'function') callback(this);
|
||||
}
|
||||
/**
|
||||
* getEvents
|
||||
* return all events found in the ical file.
|
||||
*
|
||||
* @return list of events objects
|
||||
*/
|
||||
this.getEvents = function(){
|
||||
return this.events;
|
||||
}
|
||||
|
||||
/**
|
||||
* getFutureEvents
|
||||
* return all events sheduled to take place after the current date.
|
||||
*
|
||||
* @return list of events objects
|
||||
*/
|
||||
this.getFutureEvents = function(){
|
||||
var future_events = [], current_date = new Date();
|
||||
|
||||
this.events.forEach(function(itm){
|
||||
//If the event ends after the current time, add it to the array to return.
|
||||
if(itm.DTEND > current_date) future_events.push(itm);
|
||||
});
|
||||
return future_events;
|
||||
}
|
||||
|
||||
/**
|
||||
* getPastEvents
|
||||
* return all events sheduled to take place before the current date.
|
||||
*
|
||||
* @return list of events objects
|
||||
*/
|
||||
this.getPastEvents = function(){
|
||||
var past_events = [], current_date = new Date();
|
||||
|
||||
this.events.forEach(function(itm){
|
||||
//If the event ended before the current time, add it to the array to return.
|
||||
if(itm.DTEND <= current_date) past_events.push(itm);
|
||||
});
|
||||
return past_events.reverse();
|
||||
}
|
||||
|
||||
/**
|
||||
* load
|
||||
* load a new ICAL file.
|
||||
*
|
||||
* @param ical file url
|
||||
*/
|
||||
this.load = function(ical_file){
|
||||
var tmp_this = this;
|
||||
this.raw_data = null;
|
||||
this.loadFile(ical_file, function(data){
|
||||
//if the file loads, store the data and invoke the parser
|
||||
tmp_this.raw_data = data;
|
||||
tmp_this.parseICAL(data);
|
||||
});
|
||||
}
|
||||
|
||||
//Store this so we can use it in the callback from the load function.
|
||||
var tmp_this = this;
|
||||
//Store the feed url
|
||||
this.feed_url = feed_url;
|
||||
//Load the file
|
||||
this.load(this.feed_url);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
//jQuery extension to fetch an rss feed and return it as json via YQL
|
||||
//created by dboz@airshp.com
|
||||
(function($) {
|
||||
|
||||
$.extend({
|
||||
feedToJson: function(options, callback) {
|
||||
if ($.isFunction(options)) {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
options = $.extend($.feedToJson.defaults,options);
|
||||
var url = options.yqlURL + options.yqlQS + "'" + encodeURIComponent(options.feed) + "'" + "&_nocache=" + options.cacheBuster;
|
||||
return $.getJSON(url, function(data){
|
||||
//console.log(data.query.results);
|
||||
data = data.query.results;
|
||||
$.isFunction(callback) && callback(data); //allows the callback function to be the only option
|
||||
$.isFunction(options.success) && options.success(data);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//defaults
|
||||
$.feedToJson.defaults = {
|
||||
yqlURL : 'https://query.yahooapis.com/v1/public/yql', //yql
|
||||
yqlQS : '?format=json&callback=?&q=select%20*%20from%20rss%20where%20url%3D', //yql query string
|
||||
feed:'http://instagr.am/tags/tacos/feed/recent.rss', //instagram recent posts tagged 'tacos'
|
||||
cachebuster: Math.floor((new Date().getTime()) / 1200 / 1000), //yql caches feeds, so we change the feed url every 20min
|
||||
success:null //success callback
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
// eo feedToJson
|
||||
4
js/jquery.js
vendored
4
js/jquery.js
vendored
File diff suppressed because one or more lines are too long
271
js/loader.js
Normal file
271
js/loader.js
Normal file
@@ -0,0 +1,271 @@
|
||||
/* global defaultModules, vendor */
|
||||
|
||||
/* Magic Mirror
|
||||
* Module and File loaders.
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const Loader = (function () {
|
||||
/* Create helper variables */
|
||||
|
||||
const loadedModuleFiles = [];
|
||||
const loadedFiles = [];
|
||||
const moduleObjects = [];
|
||||
|
||||
/* Private Methods */
|
||||
|
||||
/**
|
||||
* Loops thru all modules and requests load for every module.
|
||||
*/
|
||||
const loadModules = function () {
|
||||
let moduleData = getModuleData();
|
||||
|
||||
const loadNextModule = function () {
|
||||
if (moduleData.length > 0) {
|
||||
const nextModule = moduleData[0];
|
||||
loadModule(nextModule, function () {
|
||||
moduleData = moduleData.slice(1);
|
||||
loadNextModule();
|
||||
});
|
||||
} else {
|
||||
// All modules loaded. Load custom.css
|
||||
// This is done after all the modules so we can
|
||||
// overwrite all the defined styles.
|
||||
|
||||
loadFile(config.customCss, function () {
|
||||
// custom.css loaded. Start all modules.
|
||||
startModules();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
loadNextModule();
|
||||
};
|
||||
|
||||
/**
|
||||
* Loops thru all modules and requests start for every module.
|
||||
*/
|
||||
const startModules = function () {
|
||||
for (const module of moduleObjects) {
|
||||
module.start();
|
||||
}
|
||||
|
||||
// Notify core of loaded modules.
|
||||
MM.modulesStarted(moduleObjects);
|
||||
|
||||
// Starting modules also hides any modules that have requested to be initially hidden
|
||||
for (const thisModule of moduleObjects) {
|
||||
if (thisModule.data.hiddenOnStartup) {
|
||||
Log.info("Initially hiding " + thisModule.name);
|
||||
thisModule.hide();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve list of all modules.
|
||||
*
|
||||
* @returns {object[]} module data as configured in config
|
||||
*/
|
||||
const getAllModules = function () {
|
||||
return config.modules;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate array with module information including module paths.
|
||||
*
|
||||
* @returns {object[]} Module information.
|
||||
*/
|
||||
const getModuleData = function () {
|
||||
const modules = getAllModules();
|
||||
const moduleFiles = [];
|
||||
|
||||
modules.forEach(function (moduleData, index) {
|
||||
const module = moduleData.module;
|
||||
|
||||
const elements = module.split("/");
|
||||
const moduleName = elements[elements.length - 1];
|
||||
let moduleFolder = config.paths.modules + "/" + module;
|
||||
|
||||
if (defaultModules.indexOf(moduleName) !== -1) {
|
||||
moduleFolder = config.paths.modules + "/default/" + module;
|
||||
}
|
||||
|
||||
if (moduleData.disabled === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
moduleFiles.push({
|
||||
index: index,
|
||||
identifier: "module_" + index + "_" + module,
|
||||
name: moduleName,
|
||||
path: moduleFolder + "/",
|
||||
file: moduleName + ".js",
|
||||
position: moduleData.position,
|
||||
hiddenOnStartup: moduleData.hiddenOnStartup,
|
||||
header: moduleData.header,
|
||||
configDeepMerge: typeof moduleData.configDeepMerge === "boolean" ? moduleData.configDeepMerge : false,
|
||||
config: moduleData.config,
|
||||
classes: typeof moduleData.classes !== "undefined" ? moduleData.classes + " " + module : module
|
||||
});
|
||||
});
|
||||
|
||||
return moduleFiles;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load modules via ajax request and create module objects.s
|
||||
*
|
||||
* @param {object} module Information about the module we want to load.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
const loadModule = function (module, callback) {
|
||||
const url = module.path + module.file;
|
||||
|
||||
const afterLoad = function () {
|
||||
const moduleObject = Module.create(module.name);
|
||||
if (moduleObject) {
|
||||
bootstrapModule(module, moduleObject, function () {
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
if (loadedModuleFiles.indexOf(url) !== -1) {
|
||||
afterLoad();
|
||||
} else {
|
||||
loadFile(url, function () {
|
||||
loadedModuleFiles.push(url);
|
||||
afterLoad();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Bootstrap modules by setting the module data and loading the scripts & styles.
|
||||
*
|
||||
* @param {object} module Information about the module we want to load.
|
||||
* @param {Module} mObj Modules instance.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
const bootstrapModule = function (module, mObj, callback) {
|
||||
Log.info("Bootstrapping module: " + module.name);
|
||||
|
||||
mObj.setData(module);
|
||||
|
||||
mObj.loadScripts(function () {
|
||||
Log.log("Scripts loaded for: " + module.name);
|
||||
mObj.loadStyles(function () {
|
||||
Log.log("Styles loaded for: " + module.name);
|
||||
mObj.loadTranslations(function () {
|
||||
Log.log("Translations loaded for: " + module.name);
|
||||
moduleObjects.push(mObj);
|
||||
callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load a script or stylesheet by adding it to the dom.
|
||||
*
|
||||
* @param {string} fileName Path of the file we want to load.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
const loadFile = function (fileName, callback) {
|
||||
const extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
|
||||
let script, stylesheet;
|
||||
|
||||
switch (extension.toLowerCase()) {
|
||||
case "js":
|
||||
Log.log("Load script: " + fileName);
|
||||
script = document.createElement("script");
|
||||
script.type = "text/javascript";
|
||||
script.src = fileName;
|
||||
script.onload = function () {
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
script.onerror = function () {
|
||||
Log.error("Error on loading script:", fileName);
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementsByTagName("body")[0].appendChild(script);
|
||||
break;
|
||||
case "css":
|
||||
Log.log("Load stylesheet: " + fileName);
|
||||
stylesheet = document.createElement("link");
|
||||
stylesheet.rel = "stylesheet";
|
||||
stylesheet.type = "text/css";
|
||||
stylesheet.href = fileName;
|
||||
stylesheet.onload = function () {
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
stylesheet.onerror = function () {
|
||||
Log.error("Error on loading stylesheet:", fileName);
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementsByTagName("head")[0].appendChild(stylesheet);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
/* Public Methods */
|
||||
return {
|
||||
/**
|
||||
* Load all modules as defined in the config.
|
||||
*/
|
||||
loadModules: function () {
|
||||
loadModules();
|
||||
},
|
||||
|
||||
/**
|
||||
* Load a file (script or stylesheet).
|
||||
* Prevent double loading and search for files in the vendor folder.
|
||||
*
|
||||
* @param {string} fileName Path of the file we want to load.
|
||||
* @param {Module} module The module that calls the loadFile function.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
loadFile: function (fileName, module, callback) {
|
||||
if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) {
|
||||
Log.log("File already loaded: " + fileName);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileName.indexOf("http://") === 0 || fileName.indexOf("https://") === 0 || fileName.indexOf("/") !== -1) {
|
||||
// This is an absolute or relative path.
|
||||
// Load it and then return.
|
||||
loadedFiles.push(fileName.toLowerCase());
|
||||
loadFile(fileName, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vendor[fileName] !== undefined) {
|
||||
// This file is available in the vendor folder.
|
||||
// Load it from this vendor folder.
|
||||
loadedFiles.push(fileName.toLowerCase());
|
||||
loadFile(config.paths.vendor + "/" + vendor[fileName], callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// File not loaded yet.
|
||||
// Load it based on the module path.
|
||||
loadedFiles.push(fileName.toLowerCase());
|
||||
loadFile(module.file(fileName), callback);
|
||||
}
|
||||
};
|
||||
})();
|
||||
79
js/logger.js
Normal file
79
js/logger.js
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Magic Mirror
|
||||
* Log
|
||||
*
|
||||
* This logger is very simple, but needs to be extended.
|
||||
* This system can eventually be used to push the log messages to an external target.
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
(function (root, factory) {
|
||||
if (typeof exports === "object") {
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
// add timestamps in front of log messages
|
||||
require("console-stamp")(console, {
|
||||
pattern: "yyyy-mm-dd HH:MM:ss.l",
|
||||
include: ["debug", "log", "info", "warn", "error"]
|
||||
});
|
||||
}
|
||||
// Node, CommonJS-like
|
||||
module.exports = factory(root.config);
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
root.Log = factory(root.config);
|
||||
}
|
||||
})(this, function (config) {
|
||||
let logLevel;
|
||||
let enableLog;
|
||||
if (typeof exports === "object") {
|
||||
// in nodejs and not running with jest
|
||||
enableLog = process.env.JEST_WORKER_ID === undefined;
|
||||
} else {
|
||||
// in browser and not running with jsdom
|
||||
enableLog = typeof window === "object" && window.name !== "jsdom";
|
||||
}
|
||||
|
||||
if (enableLog) {
|
||||
logLevel = {
|
||||
debug: Function.prototype.bind.call(console.debug, console),
|
||||
log: Function.prototype.bind.call(console.log, console),
|
||||
info: Function.prototype.bind.call(console.info, console),
|
||||
warn: Function.prototype.bind.call(console.warn, console),
|
||||
error: Function.prototype.bind.call(console.error, console),
|
||||
group: Function.prototype.bind.call(console.group, console),
|
||||
groupCollapsed: Function.prototype.bind.call(console.groupCollapsed, console),
|
||||
groupEnd: Function.prototype.bind.call(console.groupEnd, console),
|
||||
time: Function.prototype.bind.call(console.time, console),
|
||||
timeEnd: Function.prototype.bind.call(console.timeEnd, console),
|
||||
timeStamp: Function.prototype.bind.call(console.timeStamp, console)
|
||||
};
|
||||
|
||||
logLevel.setLogLevel = function (newLevel) {
|
||||
if (newLevel) {
|
||||
Object.keys(logLevel).forEach(function (key, index) {
|
||||
if (!newLevel.includes(key.toLocaleUpperCase())) {
|
||||
logLevel[key] = function () {};
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
} else {
|
||||
logLevel = {
|
||||
debug: function () {},
|
||||
log: function () {},
|
||||
info: function () {},
|
||||
warn: function () {},
|
||||
error: function () {},
|
||||
group: function () {},
|
||||
groupCollapsed: function () {},
|
||||
groupEnd: function () {},
|
||||
time: function () {},
|
||||
timeEnd: function () {},
|
||||
timeStamp: function () {}
|
||||
};
|
||||
|
||||
logLevel.setLogLevel = function () {};
|
||||
}
|
||||
|
||||
return logLevel;
|
||||
});
|
||||
665
js/main.js
Executable file → Normal file
665
js/main.js
Executable file → Normal file
@@ -1,60 +1,615 @@
|
||||
jQuery.fn.updateWithText = function(text, speed)
|
||||
{
|
||||
var dummy = $('<div/>').html(text);
|
||||
/* global Loader, defaults, Translator */
|
||||
|
||||
if ($(this).html() != dummy.html())
|
||||
{
|
||||
$(this).fadeOut(speed/2, function() {
|
||||
$(this).html(text);
|
||||
$(this).fadeIn(speed/2, function() {
|
||||
//done
|
||||
/* Magic Mirror
|
||||
* Main System
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const MM = (function () {
|
||||
let modules = [];
|
||||
|
||||
/* Private Methods */
|
||||
|
||||
/**
|
||||
* Create dom objects for all modules that are configured for a specific position.
|
||||
*/
|
||||
const createDomObjects = function () {
|
||||
const domCreationPromises = [];
|
||||
|
||||
modules.forEach(function (module) {
|
||||
if (typeof module.data.position !== "string") {
|
||||
return;
|
||||
}
|
||||
|
||||
const wrapper = selectWrapper(module.data.position);
|
||||
|
||||
const dom = document.createElement("div");
|
||||
dom.id = module.identifier;
|
||||
dom.className = module.name;
|
||||
|
||||
if (typeof module.data.classes === "string") {
|
||||
dom.className = "module " + dom.className + " " + module.data.classes;
|
||||
}
|
||||
|
||||
dom.opacity = 0;
|
||||
wrapper.appendChild(dom);
|
||||
|
||||
const moduleHeader = document.createElement("header");
|
||||
moduleHeader.innerHTML = module.getHeader();
|
||||
moduleHeader.className = "module-header";
|
||||
dom.appendChild(moduleHeader);
|
||||
|
||||
if (typeof module.getHeader() === "undefined" || module.getHeader() !== "") {
|
||||
moduleHeader.style.display = "none;";
|
||||
} else {
|
||||
moduleHeader.style.display = "block;";
|
||||
}
|
||||
|
||||
const moduleContent = document.createElement("div");
|
||||
moduleContent.className = "module-content";
|
||||
dom.appendChild(moduleContent);
|
||||
|
||||
const domCreationPromise = updateDom(module, 0);
|
||||
domCreationPromises.push(domCreationPromise);
|
||||
domCreationPromise
|
||||
.then(function () {
|
||||
sendNotification("MODULE_DOM_CREATED", null, null, module);
|
||||
})
|
||||
.catch(Log.error);
|
||||
});
|
||||
|
||||
updateWrapperStates();
|
||||
|
||||
Promise.all(domCreationPromises).then(function () {
|
||||
sendNotification("DOM_OBJECTS_CREATED");
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the wrapper dom object for a specific position.
|
||||
*
|
||||
* @param {string} position The name of the position.
|
||||
* @returns {HTMLElement} the wrapper element
|
||||
*/
|
||||
const selectWrapper = function (position) {
|
||||
const classes = position.replace("_", " ");
|
||||
const parentWrapper = document.getElementsByClassName(classes);
|
||||
if (parentWrapper.length > 0) {
|
||||
const wrapper = parentWrapper[0].getElementsByClassName("container");
|
||||
if (wrapper.length > 0) {
|
||||
return wrapper[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Send a notification to all modules.
|
||||
*
|
||||
* @param {string} notification The identifier of the notification.
|
||||
* @param {*} payload The payload of the notification.
|
||||
* @param {Module} sender The module that sent the notification.
|
||||
* @param {Module} [sendTo] The (optional) module to send the notification to.
|
||||
*/
|
||||
const sendNotification = function (notification, payload, sender, sendTo) {
|
||||
for (const m in modules) {
|
||||
const module = modules[m];
|
||||
if (module !== sender && (!sendTo || module === sendTo)) {
|
||||
module.notificationReceived(notification, payload, sender);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the dom for a specific module.
|
||||
*
|
||||
* @param {Module} module The module that needs an update.
|
||||
* @param {number} [speed] The (optional) number of microseconds for the animation.
|
||||
* @returns {Promise} Resolved when the dom is fully updated.
|
||||
*/
|
||||
const updateDom = function (module, speed) {
|
||||
return new Promise(function (resolve) {
|
||||
const newHeader = module.getHeader();
|
||||
let newContentPromise = module.getDom();
|
||||
|
||||
if (!(newContentPromise instanceof Promise)) {
|
||||
// convert to a promise if not already one to avoid if/else's everywhere
|
||||
newContentPromise = Promise.resolve(newContentPromise);
|
||||
}
|
||||
|
||||
newContentPromise
|
||||
.then(function (newContent) {
|
||||
const updatePromise = updateDomWithContent(module, speed, newHeader, newContent);
|
||||
|
||||
updatePromise.then(resolve).catch(Log.error);
|
||||
})
|
||||
.catch(Log.error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the dom with the specified content
|
||||
*
|
||||
* @param {Module} module The module that needs an update.
|
||||
* @param {number} [speed] The (optional) number of microseconds for the animation.
|
||||
* @param {string} newHeader The new header that is generated.
|
||||
* @param {HTMLElement} newContent The new content that is generated.
|
||||
* @returns {Promise} Resolved when the module dom has been updated.
|
||||
*/
|
||||
const updateDomWithContent = function (module, speed, newHeader, newContent) {
|
||||
return new Promise(function (resolve) {
|
||||
if (module.hidden || !speed) {
|
||||
updateModuleContent(module, newHeader, newContent);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!moduleNeedsUpdate(module, newHeader, newContent)) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!speed) {
|
||||
updateModuleContent(module, newHeader, newContent);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
hideModule(module, speed / 2, function () {
|
||||
updateModuleContent(module, newHeader, newContent);
|
||||
if (!module.hidden) {
|
||||
showModule(module, speed / 2);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the content has changed.
|
||||
*
|
||||
* @param {Module} module The module to check.
|
||||
* @param {string} newHeader The new header that is generated.
|
||||
* @param {HTMLElement} newContent The new content that is generated.
|
||||
* @returns {boolean} True if the module need an update, false otherwise
|
||||
*/
|
||||
const moduleNeedsUpdate = function (module, newHeader, newContent) {
|
||||
const moduleWrapper = document.getElementById(module.identifier);
|
||||
if (moduleWrapper === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const contentWrapper = moduleWrapper.getElementsByClassName("module-content");
|
||||
const headerWrapper = moduleWrapper.getElementsByClassName("module-header");
|
||||
|
||||
let headerNeedsUpdate = false;
|
||||
let contentNeedsUpdate;
|
||||
|
||||
if (headerWrapper.length > 0) {
|
||||
headerNeedsUpdate = newHeader !== headerWrapper[0].innerHTML;
|
||||
}
|
||||
|
||||
const tempContentWrapper = document.createElement("div");
|
||||
tempContentWrapper.appendChild(newContent);
|
||||
contentNeedsUpdate = tempContentWrapper.innerHTML !== contentWrapper[0].innerHTML;
|
||||
|
||||
return headerNeedsUpdate || contentNeedsUpdate;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the content of a module on screen.
|
||||
*
|
||||
* @param {Module} module The module to check.
|
||||
* @param {string} newHeader The new header that is generated.
|
||||
* @param {HTMLElement} newContent The new content that is generated.
|
||||
*/
|
||||
const updateModuleContent = function (module, newHeader, newContent) {
|
||||
const moduleWrapper = document.getElementById(module.identifier);
|
||||
if (moduleWrapper === null) {
|
||||
return;
|
||||
}
|
||||
const headerWrapper = moduleWrapper.getElementsByClassName("module-header");
|
||||
const contentWrapper = moduleWrapper.getElementsByClassName("module-content");
|
||||
|
||||
contentWrapper[0].innerHTML = "";
|
||||
contentWrapper[0].appendChild(newContent);
|
||||
|
||||
headerWrapper[0].innerHTML = newHeader;
|
||||
if (headerWrapper.length > 0 && newHeader) {
|
||||
headerWrapper[0].style.display = "block";
|
||||
} else {
|
||||
headerWrapper[0].style.display = "none";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the module.
|
||||
*
|
||||
* @param {Module} module The module to hide.
|
||||
* @param {number} speed The speed of the hide animation.
|
||||
* @param {Function} callback Called when the animation is done.
|
||||
* @param {object} [options] Optional settings for the hide method.
|
||||
*/
|
||||
const hideModule = function (module, speed, callback, options) {
|
||||
options = options || {};
|
||||
|
||||
// set lockString if set in options.
|
||||
if (options.lockString) {
|
||||
// Log.log("Has lockstring: " + options.lockString);
|
||||
if (module.lockStrings.indexOf(options.lockString) === -1) {
|
||||
module.lockStrings.push(options.lockString);
|
||||
}
|
||||
}
|
||||
|
||||
const moduleWrapper = document.getElementById(module.identifier);
|
||||
if (moduleWrapper !== null) {
|
||||
moduleWrapper.style.transition = "opacity " + speed / 1000 + "s";
|
||||
moduleWrapper.style.opacity = 0;
|
||||
|
||||
clearTimeout(module.showHideTimer);
|
||||
module.showHideTimer = setTimeout(function () {
|
||||
// To not take up any space, we just make the position absolute.
|
||||
// since it's fade out anyway, we can see it lay above or
|
||||
// below other modules. This works way better than adjusting
|
||||
// the .display property.
|
||||
moduleWrapper.style.position = "fixed";
|
||||
|
||||
updateWrapperStates();
|
||||
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
}, speed);
|
||||
} else {
|
||||
// invoke callback even if no content, issue 1308
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the module.
|
||||
*
|
||||
* @param {Module} module The module to show.
|
||||
* @param {number} speed The speed of the show animation.
|
||||
* @param {Function} callback Called when the animation is done.
|
||||
* @param {object} [options] Optional settings for the show method.
|
||||
*/
|
||||
const showModule = function (module, speed, callback, options) {
|
||||
options = options || {};
|
||||
|
||||
// remove lockString if set in options.
|
||||
if (options.lockString) {
|
||||
const index = module.lockStrings.indexOf(options.lockString);
|
||||
if (index !== -1) {
|
||||
module.lockStrings.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are no more lockstrings set, or the force option is set.
|
||||
// Otherwise cancel show action.
|
||||
if (module.lockStrings.length !== 0 && options.force !== true) {
|
||||
Log.log("Will not show " + module.name + ". LockStrings active: " + module.lockStrings.join(","));
|
||||
if (typeof options.onError === "function") {
|
||||
options.onError(new Error("LOCK_STRING_ACTIVE"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
module.hidden = false;
|
||||
|
||||
// If forced show, clean current lockstrings.
|
||||
if (module.lockStrings.length !== 0 && options.force === true) {
|
||||
Log.log("Force show of module: " + module.name);
|
||||
module.lockStrings = [];
|
||||
}
|
||||
|
||||
const moduleWrapper = document.getElementById(module.identifier);
|
||||
if (moduleWrapper !== null) {
|
||||
moduleWrapper.style.transition = "opacity " + speed / 1000 + "s";
|
||||
// Restore the position. See hideModule() for more info.
|
||||
moduleWrapper.style.position = "static";
|
||||
|
||||
updateWrapperStates();
|
||||
|
||||
// Waiting for DOM-changes done in updateWrapperStates before we can start the animation.
|
||||
const dummy = moduleWrapper.parentElement.parentElement.offsetHeight;
|
||||
moduleWrapper.style.opacity = 1;
|
||||
|
||||
clearTimeout(module.showHideTimer);
|
||||
module.showHideTimer = setTimeout(function () {
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
}, speed);
|
||||
} else {
|
||||
// invoke callback
|
||||
if (typeof callback === "function") {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks for all positions if it has visible content.
|
||||
* If not, if will hide the position to prevent unwanted margins.
|
||||
* This method should be called by the show and hide methods.
|
||||
*
|
||||
* Example:
|
||||
* If the top_bar only contains the update notification. And no update is available,
|
||||
* the update notification is hidden. The top bar still occupies space making for
|
||||
* an ugly top margin. By using this function, the top bar will be hidden if the
|
||||
* update notification is not visible.
|
||||
*/
|
||||
const updateWrapperStates = function () {
|
||||
const positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];
|
||||
|
||||
positions.forEach(function (position) {
|
||||
const wrapper = selectWrapper(position);
|
||||
const moduleWrappers = wrapper.getElementsByClassName("module");
|
||||
|
||||
let showWrapper = false;
|
||||
Array.prototype.forEach.call(moduleWrappers, function (moduleWrapper) {
|
||||
if (moduleWrapper.style.position === "" || moduleWrapper.style.position === "static") {
|
||||
showWrapper = true;
|
||||
}
|
||||
});
|
||||
|
||||
wrapper.style.display = showWrapper ? "block" : "none";
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the core config and combines it with the system defaults.
|
||||
*/
|
||||
const loadConfig = function () {
|
||||
// FIXME: Think about how to pass config around without breaking tests
|
||||
/* eslint-disable */
|
||||
if (typeof config === "undefined") {
|
||||
config = defaults;
|
||||
Log.error("Config file is missing! Please create a config file.");
|
||||
return;
|
||||
}
|
||||
|
||||
config = Object.assign({}, defaults, config);
|
||||
/* eslint-enable */
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds special selectors on a collection of modules.
|
||||
*
|
||||
* @param {Module[]} modules Array of modules.
|
||||
*/
|
||||
const setSelectionMethodsForModules = function (modules) {
|
||||
/**
|
||||
* Filter modules with the specified classes.
|
||||
*
|
||||
* @param {string|string[]} className one or multiple classnames (array or space divided).
|
||||
* @returns {Module[]} Filtered collection of modules.
|
||||
*/
|
||||
const withClass = function (className) {
|
||||
return modulesByClass(className, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter modules without the specified classes.
|
||||
*
|
||||
* @param {string|string[]} className one or multiple classnames (array or space divided).
|
||||
* @returns {Module[]} Filtered collection of modules.
|
||||
*/
|
||||
const exceptWithClass = function (className) {
|
||||
return modulesByClass(className, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters a collection of modules based on classname(s).
|
||||
*
|
||||
* @param {string|string[]} className one or multiple classnames (array or space divided).
|
||||
* @param {boolean} include if the filter should include or exclude the modules with the specific classes.
|
||||
* @returns {Module[]} Filtered collection of modules.
|
||||
*/
|
||||
const modulesByClass = function (className, include) {
|
||||
let searchClasses = className;
|
||||
if (typeof className === "string") {
|
||||
searchClasses = className.split(" ");
|
||||
}
|
||||
|
||||
const newModules = modules.filter(function (module) {
|
||||
const classes = module.data.classes.toLowerCase().split(" ");
|
||||
|
||||
for (const searchClass of searchClasses) {
|
||||
if (classes.indexOf(searchClass.toLowerCase()) !== -1) {
|
||||
return include;
|
||||
}
|
||||
}
|
||||
|
||||
return !include;
|
||||
});
|
||||
|
||||
setSelectionMethodsForModules(newModules);
|
||||
return newModules;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a module instance from the collection.
|
||||
*
|
||||
* @param {object} module The module instance to remove from the collection.
|
||||
* @returns {Module[]} Filtered collection of modules.
|
||||
*/
|
||||
const exceptModule = function (module) {
|
||||
const newModules = modules.filter(function (mod) {
|
||||
return mod.identifier !== module.identifier;
|
||||
});
|
||||
|
||||
setSelectionMethodsForModules(newModules);
|
||||
return newModules;
|
||||
};
|
||||
|
||||
/**
|
||||
* Walks thru a collection of modules and executes the callback with the module as an argument.
|
||||
*
|
||||
* @param {Function} callback The function to execute with the module as an argument.
|
||||
*/
|
||||
const enumerate = function (callback) {
|
||||
modules.map(function (module) {
|
||||
callback(module);
|
||||
});
|
||||
};
|
||||
|
||||
if (typeof modules.withClass === "undefined") {
|
||||
Object.defineProperty(modules, "withClass", { value: withClass, enumerable: false });
|
||||
}
|
||||
if (typeof modules.exceptWithClass === "undefined") {
|
||||
Object.defineProperty(modules, "exceptWithClass", { value: exceptWithClass, enumerable: false });
|
||||
}
|
||||
if (typeof modules.exceptModule === "undefined") {
|
||||
Object.defineProperty(modules, "exceptModule", { value: exceptModule, enumerable: false });
|
||||
}
|
||||
if (typeof modules.enumerate === "undefined") {
|
||||
Object.defineProperty(modules, "enumerate", { value: enumerate, enumerable: false });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
/* Public Methods */
|
||||
|
||||
/**
|
||||
* Main init method.
|
||||
*/
|
||||
init: function () {
|
||||
Log.info("Initializing MagicMirror.");
|
||||
loadConfig();
|
||||
|
||||
Log.setLogLevel(config.logLevel);
|
||||
|
||||
Translator.loadCoreTranslations(config.language);
|
||||
Loader.loadModules();
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets called when all modules are started.
|
||||
*
|
||||
* @param {Module[]} moduleObjects All module instances.
|
||||
*/
|
||||
modulesStarted: function (moduleObjects) {
|
||||
modules = [];
|
||||
moduleObjects.forEach((module) => modules.push(module));
|
||||
|
||||
Log.info("All modules started!");
|
||||
sendNotification("ALL_MODULES_STARTED");
|
||||
|
||||
createDomObjects();
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a notification to all modules.
|
||||
*
|
||||
* @param {string} notification The identifier of the notification.
|
||||
* @param {*} payload The payload of the notification.
|
||||
* @param {Module} sender The module that sent the notification.
|
||||
*/
|
||||
sendNotification: function (notification, payload, sender) {
|
||||
if (arguments.length < 3) {
|
||||
Log.error("sendNotification: Missing arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof notification !== "string") {
|
||||
Log.error("sendNotification: Notification should be a string.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Module)) {
|
||||
Log.error("sendNotification: Sender should be a module.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Further implementation is done in the private method.
|
||||
sendNotification(notification, payload, sender);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the dom for a specific module.
|
||||
*
|
||||
* @param {Module} module The module that needs an update.
|
||||
* @param {number} [speed] The number of microseconds for the animation.
|
||||
*/
|
||||
updateDom: function (module, speed) {
|
||||
if (!(module instanceof Module)) {
|
||||
Log.error("updateDom: Sender should be a module.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!module.data.position) {
|
||||
Log.warn("module tries to update the DOM without being displayed.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Further implementation is done in the private method.
|
||||
updateDom(module, speed);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a collection of all modules currently active.
|
||||
*
|
||||
* @returns {Module[]} A collection of all modules currently active.
|
||||
*/
|
||||
getModules: function () {
|
||||
setSelectionMethodsForModules(modules);
|
||||
return modules;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the module.
|
||||
*
|
||||
* @param {Module} module The module to hide.
|
||||
* @param {number} speed The speed of the hide animation.
|
||||
* @param {Function} callback Called when the animation is done.
|
||||
* @param {object} [options] Optional settings for the hide method.
|
||||
*/
|
||||
hideModule: function (module, speed, callback, options) {
|
||||
module.hidden = true;
|
||||
hideModule(module, speed, callback, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the module.
|
||||
*
|
||||
* @param {Module} module The module to show.
|
||||
* @param {number} speed The speed of the show animation.
|
||||
* @param {Function} callback Called when the animation is done.
|
||||
* @param {object} [options] Optional settings for the show method.
|
||||
*/
|
||||
showModule: function (module, speed, callback, options) {
|
||||
// do not change module.hidden yet, only if we really show it later
|
||||
showModule(module, speed, callback, options);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
// Add polyfill for Object.assign.
|
||||
if (typeof Object.assign !== "function") {
|
||||
(function () {
|
||||
Object.assign = function (target) {
|
||||
"use strict";
|
||||
if (target === undefined || target === null) {
|
||||
throw new TypeError("Cannot convert undefined or null to object");
|
||||
}
|
||||
const output = Object(target);
|
||||
for (let index = 1; index < arguments.length; index++) {
|
||||
const source = arguments[index];
|
||||
if (source !== undefined && source !== null) {
|
||||
for (const nextKey in source) {
|
||||
if (source.hasOwnProperty(nextKey)) {
|
||||
output[nextKey] = source[nextKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
jQuery.fn.outerHTML = function(s) {
|
||||
return s
|
||||
? this.before(s).remove()
|
||||
: jQuery("<p>").append(this.eq(0).clone()).html();
|
||||
};
|
||||
|
||||
function roundVal(temp)
|
||||
{
|
||||
return Math.round(temp * 10) / 10;
|
||||
}
|
||||
|
||||
jQuery(document).ready(function($) {
|
||||
|
||||
var eventList = [];
|
||||
|
||||
var lastCompliment;
|
||||
var compliment;
|
||||
|
||||
moment.locale(config.lang);
|
||||
|
||||
//connect do Xbee monitor
|
||||
// var socket = io.connect('http://rpi-alarm.local:8082');
|
||||
// socket.on('dishwasher', function (dishwasherReady) {
|
||||
// if (dishwasherReady) {
|
||||
// $('.dishwasher').fadeIn(2000);
|
||||
// $('.lower-third').fadeOut(2000);
|
||||
// } else {
|
||||
// $('.dishwasher').fadeOut(2000);
|
||||
// $('.lower-third').fadeIn(2000);
|
||||
// }
|
||||
// });
|
||||
|
||||
version.init();
|
||||
|
||||
time.init();
|
||||
|
||||
calendar.init();
|
||||
|
||||
compliments.init();
|
||||
|
||||
weather.init();
|
||||
|
||||
news.init();
|
||||
|
||||
});
|
||||
MM.init();
|
||||
|
||||
536
js/module.js
Normal file
536
js/module.js
Normal file
@@ -0,0 +1,536 @@
|
||||
/* global Class, cloneObject, Loader, MMSocket, nunjucks, Translator */
|
||||
|
||||
/* Magic Mirror
|
||||
* Module Blueprint.
|
||||
* @typedef {Object} Module
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const Module = Class.extend({
|
||||
/*********************************************************
|
||||
* All methods (and properties) below can be subclassed. *
|
||||
*********************************************************/
|
||||
|
||||
// Set the minimum MagicMirror module version for this module.
|
||||
requiresVersion: "2.0.0",
|
||||
|
||||
// Module config defaults.
|
||||
defaults: {},
|
||||
|
||||
// Timer reference used for showHide animation callbacks.
|
||||
showHideTimer: null,
|
||||
|
||||
// Array to store lockStrings. These strings are used to lock
|
||||
// visibility when hiding and showing module.
|
||||
lockStrings: [],
|
||||
|
||||
// Storage of the nunjuck Environment,
|
||||
// This should not be referenced directly.
|
||||
// Use the nunjucksEnvironment() to get it.
|
||||
_nunjucksEnvironment: null,
|
||||
|
||||
/**
|
||||
* Called when the module is instantiated.
|
||||
*/
|
||||
init: function () {
|
||||
//Log.log(this.defaults);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the module is started.
|
||||
*/
|
||||
start: function () {
|
||||
Log.info("Starting module: " + this.name);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of scripts the module requires to be loaded.
|
||||
*
|
||||
* @returns {string[]} An array with filenames.
|
||||
*/
|
||||
getScripts: function () {
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of stylesheets the module requires to be loaded.
|
||||
*
|
||||
* @returns {string[]} An array with filenames.
|
||||
*/
|
||||
getStyles: function () {
|
||||
return [];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a map of translation files the module requires to be loaded.
|
||||
*
|
||||
* return Map<String, String> -
|
||||
*
|
||||
* @returns {*} A map with langKeys and filenames.
|
||||
*/
|
||||
getTranslations: function () {
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates the dom which needs to be displayed. This method is called by the Magic Mirror core.
|
||||
* This method can to be subclassed if the module wants to display info on the mirror.
|
||||
* Alternatively, the getTemplate method could be subclassed.
|
||||
*
|
||||
* @returns {HTMLElement|Promise} The dom or a promise with the dom to display.
|
||||
*/
|
||||
getDom: function () {
|
||||
return new Promise((resolve) => {
|
||||
const div = document.createElement("div");
|
||||
const template = this.getTemplate();
|
||||
const templateData = this.getTemplateData();
|
||||
|
||||
// Check to see if we need to render a template string or a file.
|
||||
if (/^.*((\.html)|(\.njk))$/.test(template)) {
|
||||
// the template is a filename
|
||||
this.nunjucksEnvironment().render(template, templateData, function (err, res) {
|
||||
if (err) {
|
||||
Log.error(err);
|
||||
}
|
||||
|
||||
div.innerHTML = res;
|
||||
|
||||
resolve(div);
|
||||
});
|
||||
} else {
|
||||
// the template is a template string.
|
||||
div.innerHTML = this.nunjucksEnvironment().renderString(template, templateData);
|
||||
|
||||
resolve(div);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates the header string which needs to be displayed if a user has a header configured for this module.
|
||||
* This method is called by the Magic Mirror core, but only if the user has configured a default header for the module.
|
||||
* This method needs to be subclassed if the module wants to display modified headers on the mirror.
|
||||
*
|
||||
* @returns {string} The header to display above the header.
|
||||
*/
|
||||
getHeader: function () {
|
||||
return this.data.header;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the template for the module which is used by the default getDom implementation.
|
||||
* This method needs to be subclassed if the module wants to use a template.
|
||||
* It can either return a template sting, or a template filename.
|
||||
* If the string ends with '.html' it's considered a file from within the module's folder.
|
||||
*
|
||||
* @returns {string} The template string of filename.
|
||||
*/
|
||||
getTemplate: function () {
|
||||
return '<div class="normal">' + this.name + '</div><div class="small dimmed">' + this.identifier + "</div>";
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the data to be used in the template.
|
||||
* This method needs to be subclassed if the module wants to use a custom data.
|
||||
*
|
||||
* @returns {object} The data for the template
|
||||
*/
|
||||
getTemplateData: function () {
|
||||
return {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Called by the Magic Mirror core when a notification arrives.
|
||||
*
|
||||
* @param {string} notification The identifier of the notification.
|
||||
* @param {*} payload The payload of the notification.
|
||||
* @param {Module} sender The module that sent the notification.
|
||||
*/
|
||||
notificationReceived: function (notification, payload, sender) {
|
||||
if (sender) {
|
||||
// Log.log(this.name + " received a module notification: " + notification + " from sender: " + sender.name);
|
||||
} else {
|
||||
// Log.log(this.name + " received a system notification: " + notification);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the nunjucks environment for the current module.
|
||||
* The environment is checked in the _nunjucksEnvironment instance variable.
|
||||
*
|
||||
* @returns {object} The Nunjucks Environment
|
||||
*/
|
||||
nunjucksEnvironment: function () {
|
||||
if (this._nunjucksEnvironment !== null) {
|
||||
return this._nunjucksEnvironment;
|
||||
}
|
||||
|
||||
this._nunjucksEnvironment = new nunjucks.Environment(new nunjucks.WebLoader(this.file(""), { async: true }), {
|
||||
trimBlocks: true,
|
||||
lstripBlocks: true
|
||||
});
|
||||
|
||||
this._nunjucksEnvironment.addFilter("translate", (str, variables) => {
|
||||
return nunjucks.runtime.markSafe(this.translate(str, variables));
|
||||
});
|
||||
|
||||
return this._nunjucksEnvironment;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when a socket notification arrives.
|
||||
*
|
||||
* @param {string} notification The identifier of the notification.
|
||||
* @param {*} payload The payload of the notification.
|
||||
*/
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the module is hidden.
|
||||
*/
|
||||
suspend: function () {
|
||||
Log.log(this.name + " is suspended.");
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the module is shown.
|
||||
*/
|
||||
resume: function () {
|
||||
Log.log(this.name + " is resumed.");
|
||||
},
|
||||
|
||||
/*********************************************
|
||||
* The methods below don"t need subclassing. *
|
||||
*********************************************/
|
||||
|
||||
/**
|
||||
* Set the module data.
|
||||
*
|
||||
* @param {object} data The module data
|
||||
*/
|
||||
setData: function (data) {
|
||||
this.data = data;
|
||||
this.name = data.name;
|
||||
this.identifier = data.identifier;
|
||||
this.hidden = false;
|
||||
|
||||
this.setConfig(data.config, data.configDeepMerge);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the module config and combine it with the module defaults.
|
||||
*
|
||||
* @param {object} config The combined module config.
|
||||
* @param {boolean} deep Merge module config in deep.
|
||||
*/
|
||||
setConfig: function (config, deep) {
|
||||
this.config = deep ? configMerge({}, this.defaults, config) : Object.assign({}, this.defaults, config);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a socket object. If it doesn't exist, it's created.
|
||||
* It also registers the notification callback.
|
||||
*
|
||||
* @returns {MMSocket} a socket object
|
||||
*/
|
||||
socket: function () {
|
||||
if (typeof this._socket === "undefined") {
|
||||
this._socket = new MMSocket(this.name);
|
||||
}
|
||||
|
||||
this._socket.setNotificationCallback((notification, payload) => {
|
||||
this.socketNotificationReceived(notification, payload);
|
||||
});
|
||||
|
||||
return this._socket;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieve the path to a module file.
|
||||
*
|
||||
* @param {string} file Filename
|
||||
* @returns {string} the file path
|
||||
*/
|
||||
file: function (file) {
|
||||
return (this.data.path + "/" + file).replace("//", "/");
|
||||
},
|
||||
|
||||
/**
|
||||
* Load all required stylesheets by requesting the MM object to load the files.
|
||||
*
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
loadStyles: function (callback) {
|
||||
this.loadDependencies("getStyles", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Load all required scripts by requesting the MM object to load the files.
|
||||
*
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
loadScripts: function (callback) {
|
||||
this.loadDependencies("getScripts", callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method to load all dependencies.
|
||||
*
|
||||
* @param {string} funcName Function name to call to get scripts or styles.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
loadDependencies: function (funcName, callback) {
|
||||
let dependencies = this[funcName]();
|
||||
|
||||
const loadNextDependency = () => {
|
||||
if (dependencies.length > 0) {
|
||||
const nextDependency = dependencies[0];
|
||||
Loader.loadFile(nextDependency, this, () => {
|
||||
dependencies = dependencies.slice(1);
|
||||
loadNextDependency();
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
loadNextDependency();
|
||||
},
|
||||
|
||||
/**
|
||||
* Load all translations.
|
||||
*
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
loadTranslations(callback) {
|
||||
const translations = this.getTranslations() || {};
|
||||
const language = config.language.toLowerCase();
|
||||
|
||||
const languages = Object.keys(translations);
|
||||
const fallbackLanguage = languages[0];
|
||||
|
||||
if (languages.length === 0) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const translationFile = translations[language];
|
||||
const translationsFallbackFile = translations[fallbackLanguage];
|
||||
|
||||
if (!translationFile) {
|
||||
Translator.load(this, translationsFallbackFile, true, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
Translator.load(this, translationFile, false, () => {
|
||||
if (translationFile !== translationsFallbackFile) {
|
||||
Translator.load(this, translationsFallbackFile, true, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Request the translation for a given key with optional variables and default value.
|
||||
*
|
||||
* @param {string} key The key of the string to translate
|
||||
* @param {string|object} [defaultValueOrVariables] The default value or variables for translating.
|
||||
* @param {string} [defaultValue] The default value with variables.
|
||||
* @returns {string} the translated key
|
||||
*/
|
||||
translate: function (key, defaultValueOrVariables, defaultValue) {
|
||||
if (typeof defaultValueOrVariables === "object") {
|
||||
return Translator.translate(this, key, defaultValueOrVariables) || defaultValue || "";
|
||||
}
|
||||
return Translator.translate(this, key) || defaultValueOrVariables || "";
|
||||
},
|
||||
|
||||
/**
|
||||
* Request an (animated) update of the module.
|
||||
*
|
||||
* @param {number} [speed] The speed of the animation.
|
||||
*/
|
||||
updateDom: function (speed) {
|
||||
MM.updateDom(this, speed);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a notification to all modules.
|
||||
*
|
||||
* @param {string} notification The identifier of the notification.
|
||||
* @param {*} payload The payload of the notification.
|
||||
*/
|
||||
sendNotification: function (notification, payload) {
|
||||
MM.sendNotification(notification, payload, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a socket notification to the node helper.
|
||||
*
|
||||
* @param {string} notification The identifier of the notification.
|
||||
* @param {*} payload The payload of the notification.
|
||||
*/
|
||||
sendSocketNotification: function (notification, payload) {
|
||||
this.socket().sendNotification(notification, payload);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide this module.
|
||||
*
|
||||
* @param {number} speed The speed of the hide animation.
|
||||
* @param {Function} callback Called when the animation is done.
|
||||
* @param {object} [options] Optional settings for the hide method.
|
||||
*/
|
||||
hide: function (speed, callback, options) {
|
||||
if (typeof callback === "object") {
|
||||
options = callback;
|
||||
callback = function () {};
|
||||
}
|
||||
|
||||
callback = callback || function () {};
|
||||
options = options || {};
|
||||
|
||||
MM.hideModule(
|
||||
this,
|
||||
speed,
|
||||
() => {
|
||||
this.suspend();
|
||||
callback();
|
||||
},
|
||||
options
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Show this module.
|
||||
*
|
||||
* @param {number} speed The speed of the show animation.
|
||||
* @param {Function} callback Called when the animation is done.
|
||||
* @param {object} [options] Optional settings for the show method.
|
||||
*/
|
||||
show: function (speed, callback, options) {
|
||||
if (typeof callback === "object") {
|
||||
options = callback;
|
||||
callback = function () {};
|
||||
}
|
||||
|
||||
callback = callback || function () {};
|
||||
options = options || {};
|
||||
|
||||
MM.showModule(
|
||||
this,
|
||||
speed,
|
||||
() => {
|
||||
this.resume();
|
||||
callback();
|
||||
},
|
||||
options
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Merging MagicMirror (or other) default/config script by @bugsounet
|
||||
* Merge 2 objects or/with array
|
||||
*
|
||||
* Usage:
|
||||
* -------
|
||||
* this.config = configMerge({}, this.defaults, this.config)
|
||||
* -------
|
||||
* arg1: initial object
|
||||
* arg2: config model
|
||||
* arg3: config to merge
|
||||
* -------
|
||||
* why using it ?
|
||||
* Object.assign() function don't to all job
|
||||
* it don't merge all thing in deep
|
||||
* -> object in object and array is not merging
|
||||
* -------
|
||||
*
|
||||
* Todo: idea of Mich determinate what do you want to merge or not
|
||||
*
|
||||
* @param {object} result the initial object
|
||||
* @returns {object} the merged config
|
||||
*/
|
||||
function configMerge(result) {
|
||||
const stack = Array.prototype.slice.call(arguments, 1);
|
||||
let item, key;
|
||||
|
||||
while (stack.length) {
|
||||
item = stack.shift();
|
||||
for (key in item) {
|
||||
if (item.hasOwnProperty(key)) {
|
||||
if (typeof result[key] === "object" && result[key] && Object.prototype.toString.call(result[key]) !== "[object Array]") {
|
||||
if (typeof item[key] === "object" && item[key] !== null) {
|
||||
result[key] = configMerge({}, result[key], item[key]);
|
||||
} else {
|
||||
result[key] = item[key];
|
||||
}
|
||||
} else {
|
||||
result[key] = item[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Module.definitions = {};
|
||||
|
||||
Module.create = function (name) {
|
||||
// Make sure module definition is available.
|
||||
if (!Module.definitions[name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
const moduleDefinition = Module.definitions[name];
|
||||
const clonedDefinition = cloneObject(moduleDefinition);
|
||||
|
||||
// Note that we clone the definition. Otherwise the objects are shared, which gives problems.
|
||||
const ModuleClass = Module.extend(clonedDefinition);
|
||||
|
||||
return new ModuleClass();
|
||||
};
|
||||
|
||||
Module.register = function (name, moduleDefinition) {
|
||||
if (moduleDefinition.requiresVersion) {
|
||||
Log.log("Check MagicMirror version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + window.mmVersion);
|
||||
if (cmpVersions(window.mmVersion, moduleDefinition.requiresVersion) >= 0) {
|
||||
Log.log("Version is ok!");
|
||||
} else {
|
||||
Log.warn("Version is incorrect. Skip module: '" + name + "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log.log("Module registered: " + name);
|
||||
Module.definitions[name] = moduleDefinition;
|
||||
};
|
||||
|
||||
window.Module = Module;
|
||||
|
||||
/**
|
||||
* Compare two semantic version numbers and return the difference.
|
||||
*
|
||||
* @param {string} a Version number a.
|
||||
* @param {string} b Version number b.
|
||||
* @returns {number} A positive number if a is larger than b, a negative
|
||||
* number if a is smaller and 0 if they are the same
|
||||
*/
|
||||
function cmpVersions(a, b) {
|
||||
const regExStrip0 = /(\.0+)+$/;
|
||||
const segmentsA = a.replace(regExStrip0, "").split(".");
|
||||
const segmentsB = b.replace(regExStrip0, "").split(".");
|
||||
const l = Math.min(segmentsA.length, segmentsB.length);
|
||||
|
||||
for (let i = 0; i < l; i++) {
|
||||
let diff = parseInt(segmentsA[i], 10) - parseInt(segmentsB[i], 10);
|
||||
if (diff) {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
return segmentsA.length - segmentsB.length;
|
||||
}
|
||||
80
js/moment-with-locales.min.js
vendored
80
js/moment-with-locales.min.js
vendored
File diff suppressed because one or more lines are too long
152
js/news/news.js
152
js/news/news.js
@@ -1,152 +0,0 @@
|
||||
// A lot of this code is from the original feedToJson function that was included with this project
|
||||
// The new code allows for multiple feeds to be used but a bunch of variables and such have literally been copied and pasted into this code and some help from here: http://jsfiddle.net/BDK46/
|
||||
// The original version can be found here: http://airshp.com/2011/jquery-plugin-feed-to-json/
|
||||
var news = {
|
||||
feed: config.news.feed || null,
|
||||
newsLocation: '.news',
|
||||
newsItems: [],
|
||||
seenNewsItem: [],
|
||||
_yqURL: 'https://query.yahooapis.com/v1/public/yql',
|
||||
_yqlQS: '?format=json&q=select%20*%20from%20rss%20where%20url%3D',
|
||||
_cacheBuster: Math.floor((new Date().getTime()) / 1200 / 1000),
|
||||
_failedAttempts: 0,
|
||||
fetchInterval: config.news.fetchInterval || 60000,
|
||||
updateInterval: config.news.interval || 5500,
|
||||
fadeInterval: 2000,
|
||||
intervalId: null,
|
||||
fetchNewsIntervalId: null
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the query string that will be used to grab a converted RSS feed into a JSON object via Yahoo
|
||||
* @param {string} feed The original location of the RSS feed
|
||||
* @return {string} The new location of the RSS feed provided by Yahoo
|
||||
*/
|
||||
news.buildQueryString = function (feed) {
|
||||
|
||||
return this._yqURL + this._yqlQS + '\'' + encodeURIComponent(feed) + '\'';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the news for each feed provided in the config file
|
||||
*/
|
||||
news.fetchNews = function () {
|
||||
|
||||
// Reset the news feed
|
||||
this.newsItems = [];
|
||||
|
||||
this.feed.forEach(function (_curr) {
|
||||
|
||||
var _yqUrlString = this.buildQueryString(_curr);
|
||||
this.fetchFeed(_yqUrlString);
|
||||
|
||||
}.bind(this));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a GET request to Yahoo's service
|
||||
* @param {string} yqUrl The URL being used to grab the RSS feed (in JSON format)
|
||||
*/
|
||||
news.fetchFeed = function (yqUrl) {
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
datatype:'jsonp',
|
||||
url: yqUrl,
|
||||
success: function (data) {
|
||||
|
||||
if (data.query.count > 0) {
|
||||
this.parseFeed(data.query.results.item);
|
||||
} else {
|
||||
console.error('No feed results for: ' + yqUrl);
|
||||
}
|
||||
|
||||
}.bind(this),
|
||||
error: function () {
|
||||
// non-specific error message that should be updated
|
||||
console.error('No feed results for: ' + yqUrl);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses each item in a single news feed
|
||||
* @param {Object} data The news feed that was returned by Yahoo
|
||||
* @return {boolean} Confirms that the feed was parsed correctly
|
||||
*/
|
||||
news.parseFeed = function (data) {
|
||||
|
||||
var _rssItems = [];
|
||||
|
||||
for (var i = 0, count = data.length; i < count; i++) {
|
||||
|
||||
_rssItems.push(data[i].title);
|
||||
|
||||
}
|
||||
|
||||
this.newsItems = this.newsItems.concat(_rssItems);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through each available and unseen news feed after it has been retrieved from Yahoo and shows it on the screen
|
||||
* When all news titles have been exhausted, the list resets and randomly chooses from the original set of items
|
||||
* @return {boolean} Confirms that there is a list of news items to loop through and that one has been shown on the screen
|
||||
*/
|
||||
news.showNews = function () {
|
||||
|
||||
// If all items have been seen, swap seen to unseen
|
||||
if (this.newsItems.length === 0 && this.seenNewsItem.length !== 0) {
|
||||
|
||||
if (this._failedAttempts === 20) {
|
||||
console.error('Failed to show a news story 20 times, stopping any attempts');
|
||||
return false;
|
||||
}
|
||||
|
||||
this._failedAttempts++;
|
||||
|
||||
setTimeout(function () {
|
||||
this.showNews();
|
||||
}.bind(this), 3000);
|
||||
|
||||
} else if (this.newsItems.length === 0 && this.seenNewsItem.length !== 0) {
|
||||
this.newsItems = this.seenNewsItem.splice(0);
|
||||
}
|
||||
|
||||
var _location = Math.floor(Math.random() * this.newsItems.length);
|
||||
|
||||
var _item = news.newsItems.splice(_location, 1)[0];
|
||||
|
||||
this.seenNewsItem.push(_item);
|
||||
|
||||
$(this.newsLocation).updateWithText(_item, this.fadeInterval);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
news.init = function () {
|
||||
|
||||
if (this.feed === null || (this.feed instanceof Array === false && typeof this.feed !== 'string')) {
|
||||
return false;
|
||||
} else if (typeof this.feed === 'string') {
|
||||
this.feed = [this.feed];
|
||||
}
|
||||
|
||||
this.fetchNews();
|
||||
this.showNews();
|
||||
|
||||
this.fetchNewsIntervalId = setInterval(function () {
|
||||
this.fetchNews()
|
||||
}.bind(this), this.fetchInterval)
|
||||
|
||||
this.intervalId = setInterval(function () {
|
||||
this.showNews();
|
||||
}.bind(this), this.updateInterval);
|
||||
|
||||
}
|
||||
146
js/node_helper.js
Normal file
146
js/node_helper.js
Normal file
@@ -0,0 +1,146 @@
|
||||
/* Magic Mirror
|
||||
* Node Helper Superclass
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const Class = require("./class.js");
|
||||
const Log = require("logger");
|
||||
const express = require("express");
|
||||
|
||||
const NodeHelper = Class.extend({
|
||||
init() {
|
||||
Log.log("Initializing new module helper ...");
|
||||
},
|
||||
|
||||
loaded(callback) {
|
||||
Log.log(`Module helper loaded: ${this.name}`);
|
||||
callback();
|
||||
},
|
||||
|
||||
start() {
|
||||
Log.log(`Starting module helper: ${this.name}`);
|
||||
},
|
||||
|
||||
/* stop()
|
||||
* Called when the MagicMirror server receives a `SIGINT`
|
||||
* Close any open connections, stop any sub-processes and
|
||||
* gracefully exit the module.
|
||||
*
|
||||
*/
|
||||
stop() {
|
||||
Log.log(`Stopping module helper: ${this.name}`);
|
||||
},
|
||||
|
||||
/* socketNotificationReceived(notification, payload)
|
||||
* This method is called when a socket notification arrives.
|
||||
*
|
||||
* argument notification string - The identifier of the notification.
|
||||
* argument payload mixed - The payload of the notification.
|
||||
*/
|
||||
socketNotificationReceived(notification, payload) {
|
||||
Log.log(`${this.name} received a socket notification: ${notification} - Payload: ${payload}`);
|
||||
},
|
||||
|
||||
/* setName(name)
|
||||
* Set the module name.
|
||||
*
|
||||
* argument name string - Module name.
|
||||
*/
|
||||
setName(name) {
|
||||
this.name = name;
|
||||
},
|
||||
|
||||
/* setPath(path)
|
||||
* Set the module path.
|
||||
*
|
||||
* argument path string - Module path.
|
||||
*/
|
||||
setPath(path) {
|
||||
this.path = path;
|
||||
},
|
||||
|
||||
/* sendSocketNotification(notification, payload)
|
||||
* Send a socket notification to the node helper.
|
||||
*
|
||||
* argument notification string - The identifier of the notification.
|
||||
* argument payload mixed - The payload of the notification.
|
||||
*/
|
||||
sendSocketNotification(notification, payload) {
|
||||
this.io.of(this.name).emit(notification, payload);
|
||||
},
|
||||
|
||||
/* setExpressApp(app)
|
||||
* Sets the express app object for this module.
|
||||
* This allows you to host files from the created webserver.
|
||||
*
|
||||
* argument app Express app - The Express app object.
|
||||
*/
|
||||
setExpressApp(app) {
|
||||
this.expressApp = app;
|
||||
|
||||
app.use(`/${this.name}`, express.static(`${this.path}/public`));
|
||||
},
|
||||
|
||||
/* setSocketIO(io)
|
||||
* Sets the socket io object for this module.
|
||||
* Binds message receiver.
|
||||
*
|
||||
* argument io Socket.io - The Socket io object.
|
||||
*/
|
||||
setSocketIO(io) {
|
||||
this.io = io;
|
||||
|
||||
Log.log(`Connecting socket for: ${this.name}`);
|
||||
|
||||
io.of(this.name).on("connection", (socket) => {
|
||||
// add a catch all event.
|
||||
const onevent = socket.onevent;
|
||||
socket.onevent = function (packet) {
|
||||
const args = packet.data || [];
|
||||
onevent.call(this, packet); // original call
|
||||
packet.data = ["*"].concat(args);
|
||||
onevent.call(this, packet); // additional call to catch-all
|
||||
};
|
||||
|
||||
// register catch all.
|
||||
socket.on("*", (notification, payload) => {
|
||||
if (notification !== "*") {
|
||||
this.socketNotificationReceived(notification, payload);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
NodeHelper.checkFetchStatus = function (response) {
|
||||
// response.status >= 200 && response.status < 300
|
||||
if (response.ok) {
|
||||
return response;
|
||||
} else {
|
||||
throw Error(response.statusText);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Look at the specified error and return an appropriate error type, that
|
||||
* can be translated to a detailed error message
|
||||
*
|
||||
* @param {Error} error the error from fetching something
|
||||
* @returns {string} the string of the detailed error message in the translations
|
||||
*/
|
||||
NodeHelper.checkFetchError = function (error) {
|
||||
let error_type = "MODULE_ERROR_UNSPECIFIED";
|
||||
if (error.code === "EAI_AGAIN") {
|
||||
error_type = "MODULE_ERROR_NO_CONNECTION";
|
||||
} else if (error.message === "Unauthorized") {
|
||||
error_type = "MODULE_ERROR_UNAUTHORIZED";
|
||||
}
|
||||
return error_type;
|
||||
};
|
||||
|
||||
NodeHelper.create = function (moduleDefinition) {
|
||||
return NodeHelper.extend(moduleDefinition);
|
||||
};
|
||||
|
||||
module.exports = NodeHelper;
|
||||
1910
js/rrule.js
1910
js/rrule.js
File diff suppressed because it is too large
Load Diff
112
js/server.js
Normal file
112
js/server.js
Normal file
@@ -0,0 +1,112 @@
|
||||
/* Magic Mirror
|
||||
* Server
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const express = require("express");
|
||||
const app = require("express")();
|
||||
const path = require("path");
|
||||
const ipfilter = require("express-ipfilter").IpFilter;
|
||||
const fs = require("fs");
|
||||
const helmet = require("helmet");
|
||||
|
||||
const Log = require("logger");
|
||||
const Utils = require("./utils.js");
|
||||
|
||||
/**
|
||||
* Server
|
||||
*
|
||||
* @param {object} config The MM config
|
||||
* @param {Function} callback Function called when done.
|
||||
* @class
|
||||
*/
|
||||
function Server(config, callback) {
|
||||
const port = process.env.MM_PORT || config.port;
|
||||
const serverSockets = new Set();
|
||||
|
||||
let server = null;
|
||||
if (config.useHttps) {
|
||||
const options = {
|
||||
key: fs.readFileSync(config.httpsPrivateKey),
|
||||
cert: fs.readFileSync(config.httpsCertificate)
|
||||
};
|
||||
server = require("https").Server(options, app);
|
||||
} else {
|
||||
server = require("http").Server(app);
|
||||
}
|
||||
const io = require("socket.io")(server, {
|
||||
cors: {
|
||||
origin: /.*$/,
|
||||
credentials: true
|
||||
},
|
||||
allowEIO3: true
|
||||
});
|
||||
|
||||
server.on("connection", (socket) => {
|
||||
serverSockets.add(socket);
|
||||
socket.on("close", () => {
|
||||
serverSockets.delete(socket);
|
||||
});
|
||||
});
|
||||
|
||||
Log.log(`Starting server on port ${port} ... `);
|
||||
|
||||
server.listen(port, config.address || "localhost");
|
||||
|
||||
if (config.ipWhitelist instanceof Array && config.ipWhitelist.length === 0) {
|
||||
Log.warn(Utils.colors.warn("You're using a full whitelist configuration to allow for all IPs"));
|
||||
}
|
||||
|
||||
app.use(function (req, res, next) {
|
||||
ipfilter(config.ipWhitelist, { mode: config.ipWhitelist.length === 0 ? "deny" : "allow", log: false })(req, res, function (err) {
|
||||
if (err === undefined) {
|
||||
return next();
|
||||
}
|
||||
Log.log(err.message);
|
||||
res.status(403).send("This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.");
|
||||
});
|
||||
});
|
||||
app.use(helmet({ contentSecurityPolicy: false }));
|
||||
|
||||
app.use("/js", express.static(__dirname));
|
||||
|
||||
const directories = ["/config", "/css", "/fonts", "/modules", "/vendor", "/translations", "/tests/configs"];
|
||||
for (const directory of directories) {
|
||||
app.use(directory, express.static(path.resolve(global.root_path + directory)));
|
||||
}
|
||||
|
||||
app.get("/version", function (req, res) {
|
||||
res.send(global.version);
|
||||
});
|
||||
|
||||
app.get("/config", function (req, res) {
|
||||
res.send(config);
|
||||
});
|
||||
|
||||
app.get("/", function (req, res) {
|
||||
let html = fs.readFileSync(path.resolve(`${global.root_path}/index.html`), { encoding: "utf8" });
|
||||
html = html.replace("#VERSION#", global.version);
|
||||
|
||||
let configFile = "config/config.js";
|
||||
if (typeof global.configuration_file !== "undefined") {
|
||||
configFile = global.configuration_file;
|
||||
}
|
||||
html = html.replace("#CONFIG_FILE#", configFile);
|
||||
|
||||
res.send(html);
|
||||
});
|
||||
|
||||
if (typeof callback === "function") {
|
||||
callback(app, io);
|
||||
}
|
||||
|
||||
this.close = function () {
|
||||
for (const socket of serverSockets.values()) {
|
||||
socket.destroy();
|
||||
}
|
||||
server.close();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = Server;
|
||||
2
js/socket.io.min.js
vendored
2
js/socket.io.min.js
vendored
File diff suppressed because one or more lines are too long
53
js/socketclient.js
Normal file
53
js/socketclient.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/* global io */
|
||||
|
||||
/* Magic Mirror
|
||||
* TODO add description
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const MMSocket = function (moduleName) {
|
||||
if (typeof moduleName !== "string") {
|
||||
throw new Error("Please set the module name for the MMSocket.");
|
||||
}
|
||||
|
||||
this.moduleName = moduleName;
|
||||
|
||||
// Private Methods
|
||||
let base = "/";
|
||||
if (typeof config !== "undefined" && typeof config.basePath !== "undefined") {
|
||||
base = config.basePath;
|
||||
}
|
||||
this.socket = io("/" + this.moduleName, {
|
||||
path: base + "socket.io"
|
||||
});
|
||||
|
||||
let notificationCallback = function () {};
|
||||
|
||||
const onevent = this.socket.onevent;
|
||||
this.socket.onevent = (packet) => {
|
||||
const args = packet.data || [];
|
||||
onevent.call(this.socket, packet); // original call
|
||||
packet.data = ["*"].concat(args);
|
||||
onevent.call(this.socket, packet); // additional call to catch-all
|
||||
};
|
||||
|
||||
// register catch all.
|
||||
this.socket.on("*", (notification, payload) => {
|
||||
if (notification !== "*") {
|
||||
notificationCallback(notification, payload);
|
||||
}
|
||||
});
|
||||
|
||||
// Public Methods
|
||||
this.setNotificationCallback = (callback) => {
|
||||
notificationCallback = callback;
|
||||
};
|
||||
|
||||
this.sendNotification = (notification, payload) => {
|
||||
if (typeof payload === "undefined") {
|
||||
payload = {};
|
||||
}
|
||||
this.socket.emit(notification, payload);
|
||||
};
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
var time = {
|
||||
timeFormat: config.time.timeFormat || 24,
|
||||
dateLocation: '.date',
|
||||
timeLocation: '.time',
|
||||
updateInterval: 1000,
|
||||
intervalId: null
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the time that is shown on the screen
|
||||
*/
|
||||
time.updateTime = function () {
|
||||
|
||||
var _now = moment(),
|
||||
_date = _now.format('dddd, LL');
|
||||
|
||||
$(this.dateLocation).html(_date);
|
||||
$(this.timeLocation).html(_now.format(this._timeFormat+':mm[<span class="sec">]ss[</span>]'));
|
||||
|
||||
}
|
||||
|
||||
time.init = function () {
|
||||
|
||||
if (parseInt(time.timeFormat) === 12) {
|
||||
time._timeFormat = 'hh'
|
||||
} else {
|
||||
time._timeFormat = 'HH';
|
||||
}
|
||||
|
||||
this.intervalId = setInterval(function () {
|
||||
this.updateTime();
|
||||
}.bind(this), 1000);
|
||||
|
||||
}
|
||||
155
js/translator.js
Normal file
155
js/translator.js
Normal file
@@ -0,0 +1,155 @@
|
||||
/* global translations */
|
||||
|
||||
/* Magic Mirror
|
||||
* Translator (l10n)
|
||||
*
|
||||
* By Christopher Fenner https://github.com/CFenner
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const Translator = (function () {
|
||||
/**
|
||||
* Load a JSON file via XHR.
|
||||
*
|
||||
* @param {string} file Path of the file we want to load.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
function loadJSON(file, callback) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.overrideMimeType("application/json");
|
||||
xhr.open("GET", file, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
// needs error handler try/catch at least
|
||||
let fileinfo = null;
|
||||
try {
|
||||
fileinfo = JSON.parse(xhr.responseText);
|
||||
} catch (exception) {
|
||||
// nothing here, but don't die
|
||||
Log.error(" loading json file =" + file + " failed");
|
||||
}
|
||||
callback(fileinfo);
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
return {
|
||||
coreTranslations: {},
|
||||
coreTranslationsFallback: {},
|
||||
translations: {},
|
||||
translationsFallback: {},
|
||||
|
||||
/**
|
||||
* Load a translation for a given key for a given module.
|
||||
*
|
||||
* @param {Module} module The module to load the translation for.
|
||||
* @param {string} key The key of the text to translate.
|
||||
* @param {object} variables The variables to use within the translation template (optional)
|
||||
* @returns {string} the translated key
|
||||
*/
|
||||
translate: function (module, key, variables) {
|
||||
variables = variables || {}; //Empty object by default
|
||||
|
||||
/**
|
||||
* Combines template and variables like:
|
||||
* template: "Please wait for {timeToWait} before continuing with {work}."
|
||||
* variables: {timeToWait: "2 hours", work: "painting"}
|
||||
* to: "Please wait for 2 hours before continuing with painting."
|
||||
*
|
||||
* @param {string} template Text with placeholder
|
||||
* @param {object} variables Variables for the placeholder
|
||||
* @returns {string} the template filled with the variables
|
||||
*/
|
||||
function createStringFromTemplate(template, variables) {
|
||||
if (Object.prototype.toString.call(template) !== "[object String]") {
|
||||
return template;
|
||||
}
|
||||
if (variables.fallback && !template.match(new RegExp("{.+}"))) {
|
||||
template = variables.fallback;
|
||||
}
|
||||
return template.replace(new RegExp("{([^}]+)}", "g"), function (_unused, varName) {
|
||||
return varName in variables ? variables[varName] : "{" + varName + "}";
|
||||
});
|
||||
}
|
||||
|
||||
if (this.translations[module.name] && key in this.translations[module.name]) {
|
||||
// Log.log("Got translation for " + key + " from module translation: ");
|
||||
return createStringFromTemplate(this.translations[module.name][key], variables);
|
||||
}
|
||||
|
||||
if (key in this.coreTranslations) {
|
||||
// Log.log("Got translation for " + key + " from core translation.");
|
||||
return createStringFromTemplate(this.coreTranslations[key], variables);
|
||||
}
|
||||
|
||||
if (this.translationsFallback[module.name] && key in this.translationsFallback[module.name]) {
|
||||
// Log.log("Got translation for " + key + " from module translation fallback.");
|
||||
return createStringFromTemplate(this.translationsFallback[module.name][key], variables);
|
||||
}
|
||||
|
||||
if (key in this.coreTranslationsFallback) {
|
||||
// Log.log("Got translation for " + key + " from core translation fallback.");
|
||||
return createStringFromTemplate(this.coreTranslationsFallback[key], variables);
|
||||
}
|
||||
|
||||
return key;
|
||||
},
|
||||
|
||||
/**
|
||||
* Load a translation file (json) and remember the data.
|
||||
*
|
||||
* @param {Module} module The module to load the translation file for.
|
||||
* @param {string} file Path of the file we want to load.
|
||||
* @param {boolean} isFallback Flag to indicate fallback translations.
|
||||
* @param {Function} callback Function called when done.
|
||||
*/
|
||||
load(module, file, isFallback, callback) {
|
||||
Log.log(`${module.name} - Load translation${isFallback && " fallback"}: ${file}`);
|
||||
|
||||
if (this.translationsFallback[module.name]) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
loadJSON(module.file(file), (json) => {
|
||||
const property = isFallback ? "translationsFallback" : "translations";
|
||||
this[property][module.name] = json;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the core translations.
|
||||
*
|
||||
* @param {string} lang The language identifier of the core language.
|
||||
*/
|
||||
loadCoreTranslations: function (lang) {
|
||||
if (lang in translations) {
|
||||
Log.log("Loading core translation file: " + translations[lang]);
|
||||
loadJSON(translations[lang], (translations) => {
|
||||
this.coreTranslations = translations;
|
||||
});
|
||||
} else {
|
||||
Log.log("Configured language not found in core translations.");
|
||||
}
|
||||
|
||||
this.loadCoreTranslationsFallback();
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the core translations fallback.
|
||||
* The first language defined in translations.js will be used.
|
||||
*/
|
||||
loadCoreTranslationsFallback: function () {
|
||||
let first = Object.keys(translations)[0];
|
||||
if (first) {
|
||||
Log.log("Loading core translation fallback file: " + translations[first]);
|
||||
loadJSON(translations[first], (translations) => {
|
||||
this.coreTranslationsFallback = translations;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
window.Translator = Translator;
|
||||
16
js/utils.js
Normal file
16
js/utils.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Magic Mirror
|
||||
* Utils
|
||||
*
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const colors = require("colors/safe");
|
||||
|
||||
module.exports = {
|
||||
colors: {
|
||||
warn: colors.yellow,
|
||||
error: colors.red,
|
||||
info: colors.blue,
|
||||
pass: colors.green
|
||||
}
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
var version = {
|
||||
updateInterval: 600000,
|
||||
intervalId: null
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the version and refreshes the page if a new version has been pulled
|
||||
*/
|
||||
version.checkVersion = function () {
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'controllers/hash.php',
|
||||
success: function (data) {
|
||||
// The githash variable is located in index.php
|
||||
if (data && data.gitHash !== gitHash) {
|
||||
window.location.reload();
|
||||
window.location.href = window.location.href;
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
version.init = function () {
|
||||
|
||||
this.intervalId = setInterval(function () {
|
||||
this.checkVersion();
|
||||
}.bind(this), this.updateInterval);
|
||||
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
var weather = {
|
||||
// Default language is Dutch because that is what the original author used
|
||||
lang: config.lang || 'nl',
|
||||
params: config.weather.params || null,
|
||||
iconTable: {
|
||||
'01d':'wi-day-sunny',
|
||||
'02d':'wi-day-cloudy',
|
||||
'03d':'wi-cloudy',
|
||||
'04d':'wi-cloudy-windy',
|
||||
'09d':'wi-showers',
|
||||
'10d':'wi-rain',
|
||||
'11d':'wi-thunderstorm',
|
||||
'13d':'wi-snow',
|
||||
'50d':'wi-fog',
|
||||
'01n':'wi-night-clear',
|
||||
'02n':'wi-night-cloudy',
|
||||
'03n':'wi-night-cloudy',
|
||||
'04n':'wi-night-cloudy',
|
||||
'09n':'wi-night-showers',
|
||||
'10n':'wi-night-rain',
|
||||
'11n':'wi-night-thunderstorm',
|
||||
'13n':'wi-night-snow',
|
||||
'50n':'wi-night-alt-cloudy-windy'
|
||||
},
|
||||
temperatureLocation: '.temp',
|
||||
windSunLocation: '.windsun',
|
||||
forecastLocation: '.forecast',
|
||||
apiVersion: '2.5',
|
||||
apiBase: 'http://api.openweathermap.org/data/',
|
||||
weatherEndpoint: 'weather',
|
||||
forecastEndpoint: 'forecast/daily',
|
||||
updateInterval: config.weather.interval || 6000,
|
||||
fadeInterval: config.weather.fadeInterval || 1000,
|
||||
intervalId: null
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a float to one decimal place
|
||||
* @param {float} temperature The temperature to be rounded
|
||||
* @return {float} The new floating point value
|
||||
*/
|
||||
weather.roundValue = function (temperature) {
|
||||
return parseFloat(temperature).toFixed(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the wind speed (km/h) into the values given by the Beaufort Wind Scale
|
||||
* @see http://www.spc.noaa.gov/faq/tornado/beaufort.html
|
||||
* @param {int} kmh The wind speed in Kilometers Per Hour
|
||||
* @return {int} The wind speed converted into its corresponding Beaufort number
|
||||
*/
|
||||
weather.ms2Beaufort = function(ms) {
|
||||
var kmh = ms * 60 * 60 / 1000;
|
||||
var speeds = [1, 5, 11, 19, 28, 38, 49, 61, 74, 88, 102, 117, 1000];
|
||||
for (var beaufort in speeds) {
|
||||
var speed = speeds[beaufort];
|
||||
if (speed > kmh) {
|
||||
return beaufort;
|
||||
}
|
||||
}
|
||||
return 12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current temperature and weather patter from the OpenWeatherMap API
|
||||
*/
|
||||
weather.updateCurrentWeather = function () {
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: weather.apiBase + '/' + weather.apiVersion + '/' + weather.weatherEndpoint,
|
||||
dataType: 'json',
|
||||
data: weather.params,
|
||||
success: function (data) {
|
||||
|
||||
var _temperature = this.roundValue(data.main.temp),
|
||||
_temperatureMin = this.roundValue(data.main.temp_min),
|
||||
_temperatureMax = this.roundValue(data.main.temp_max),
|
||||
_wind = this.roundValue(data.wind.speed),
|
||||
_iconClass = this.iconTable[data.weather[0].icon];
|
||||
|
||||
var _icon = '<span class="icon ' + _iconClass + ' dimmed wi"></span>';
|
||||
|
||||
var _newTempHtml = _icon + '' + _temperature + '°';
|
||||
|
||||
$(this.temperatureLocation).updateWithText(_newTempHtml, this.fadeInterval);
|
||||
|
||||
var _now = moment().format('HH:mm'),
|
||||
_sunrise = moment(data.sys.sunrise*1000).format('HH:mm'),
|
||||
_sunset = moment(data.sys.sunset*1000).format('HH:mm');
|
||||
|
||||
var _newWindHtml = '<span class="wi wi-strong-wind xdimmed"></span> ' + this.ms2Beaufort(_wind),
|
||||
_newSunHtml = '<span class="wi wi-sunrise xdimmed"></span> ' + _sunrise;
|
||||
|
||||
if (_sunrise < _now && _sunset > _now) {
|
||||
_newSunHtml = '<span class="wi wi-sunset xdimmed"></span> ' + _sunset;
|
||||
}
|
||||
|
||||
$(this.windSunLocation).updateWithText(_newWindHtml + ' ' + _newSunHtml, this.fadeInterval);
|
||||
|
||||
}.bind(this),
|
||||
error: function () {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the 5 Day Forecast from the OpenWeatherMap API
|
||||
*/
|
||||
weather.updateWeatherForecast = function () {
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: weather.apiBase + '/' + weather.apiVersion + '/' + weather.forecastEndpoint,
|
||||
data: weather.params,
|
||||
success: function (data) {
|
||||
|
||||
var _opacity = 1,
|
||||
_forecastHtml = '';
|
||||
|
||||
_forecastHtml += '<table class="forecast-table">';
|
||||
|
||||
for (var i = 0, count = data.list.length; i < count; i++) {
|
||||
|
||||
var _forecast = data.list[i];
|
||||
|
||||
_forecastHtml += '<tr style="opacity:' + _opacity + '">';
|
||||
|
||||
_forecastHtml += '<td class="day">' + moment(_forecast.dt, 'X').format('ddd') + '</td>';
|
||||
_forecastHtml += '<td class="icon-small ' + this.iconTable[_forecast.weather[0].icon] + '"></td>';
|
||||
_forecastHtml += '<td class="temp-max">' + this.roundValue(_forecast.temp.max) + '</td>';
|
||||
_forecastHtml += '<td class="temp-min">' + this.roundValue(_forecast.temp.min) + '</td>';
|
||||
|
||||
_forecastHtml += '</tr>';
|
||||
|
||||
_opacity -= 0.155;
|
||||
|
||||
}
|
||||
|
||||
_forecastHtml += '</table>';
|
||||
|
||||
$(this.forecastLocation).updateWithText(_forecastHtml, this.fadeInterval);
|
||||
|
||||
}.bind(this),
|
||||
error: function () {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
weather.init = function () {
|
||||
|
||||
if (this.params.lang === undefined) {
|
||||
this.params.lang = this.lang;
|
||||
}
|
||||
|
||||
if (this.params.cnt === undefined) {
|
||||
this.params.cnt = 5;
|
||||
}
|
||||
|
||||
this.intervalId = setInterval(function () {
|
||||
this.updateCurrentWeather();
|
||||
this.updateWeatherForecast();
|
||||
}.bind(this), this.updateInterval);
|
||||
|
||||
}
|
||||
10
jsconfig.json
Normal file
10
jsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=759670
|
||||
// for the documentation about the jsconfig.json format
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"exclude": ["modules", "node_modules"]
|
||||
}
|
||||
31
module-types.ts
Normal file
31
module-types.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
type ModuleProperties = {
|
||||
defaults?: object;
|
||||
start?(): void;
|
||||
getHeader?(): string;
|
||||
getTemplate?(): string;
|
||||
getTemplateData?(): object;
|
||||
notificationReceived?(notification: string, payload: any, sender: object): void;
|
||||
socketNotificationReceived?(notification: string, payload: any): void;
|
||||
suspend?(): void;
|
||||
resume?(): void;
|
||||
getDom?(): HTMLElement;
|
||||
getStyles?(): string[];
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
export declare const Module: {
|
||||
register(moduleName: string, moduleProperties: ModuleProperties): void;
|
||||
};
|
||||
|
||||
export declare const Log: {
|
||||
info(message?: any, ...optionalParams: any[]): void;
|
||||
log(message?: any, ...optionalParams: any[]): void;
|
||||
error(message?: any, ...optionalParams: any[]): void;
|
||||
warn(message?: any, ...optionalParams: any[]): void;
|
||||
group(groupTitle?: string, ...optionalParams: any[]): void;
|
||||
groupCollapsed(groupTitle?: string, ...optionalParams: any[]): void;
|
||||
groupEnd(): void;
|
||||
time(timerName?: string): void;
|
||||
timeEnd(timerName?: string): void;
|
||||
timeStamp(timerName?: string): void;
|
||||
};
|
||||
5
modules/default/alert/README.md
Normal file
5
modules/default/alert/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Module: Alert
|
||||
|
||||
The alert module is one of the default modules of the MagicMirror. This module displays notifications from other modules.
|
||||
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/alert.html).
|
||||
167
modules/default/alert/alert.js
Normal file
167
modules/default/alert/alert.js
Normal file
@@ -0,0 +1,167 @@
|
||||
/* global NotificationFx */
|
||||
|
||||
/* Magic Mirror
|
||||
* Module: alert
|
||||
*
|
||||
* By Paul-Vincent Roll https://paulvincentroll.com/
|
||||
* MIT Licensed.
|
||||
*/
|
||||
Module.register("alert", {
|
||||
defaults: {
|
||||
// scale|slide|genie|jelly|flip|bouncyflip|exploader
|
||||
effect: "slide",
|
||||
// scale|slide|genie|jelly|flip|bouncyflip|exploader
|
||||
alert_effect: "jelly",
|
||||
//time a notification is displayed in seconds
|
||||
display_time: 3500,
|
||||
//Position
|
||||
position: "center",
|
||||
//shown at startup
|
||||
welcome_message: false
|
||||
},
|
||||
getScripts: function () {
|
||||
return ["notificationFx.js"];
|
||||
},
|
||||
getStyles: function () {
|
||||
return ["notificationFx.css", "font-awesome.css"];
|
||||
},
|
||||
// Define required translations.
|
||||
getTranslations: function () {
|
||||
return {
|
||||
en: "translations/en.json",
|
||||
de: "translations/de.json",
|
||||
nl: "translations/nl.json"
|
||||
};
|
||||
},
|
||||
show_notification: function (message) {
|
||||
if (this.config.effect === "slide") {
|
||||
this.config.effect = this.config.effect + "-" + this.config.position;
|
||||
}
|
||||
let msg = "";
|
||||
if (message.title) {
|
||||
msg += "<span class='thin dimmed medium'>" + message.title + "</span>";
|
||||
}
|
||||
if (message.message) {
|
||||
if (msg !== "") {
|
||||
msg += "<br />";
|
||||
}
|
||||
msg += "<span class='light bright small'>" + message.message + "</span>";
|
||||
}
|
||||
|
||||
new NotificationFx({
|
||||
message: msg,
|
||||
layout: "growl",
|
||||
effect: this.config.effect,
|
||||
ttl: message.timer !== undefined ? message.timer : this.config.display_time
|
||||
}).show();
|
||||
},
|
||||
show_alert: function (params, sender) {
|
||||
let image = "";
|
||||
//Set standard params if not provided by module
|
||||
if (typeof params.timer === "undefined") {
|
||||
params.timer = null;
|
||||
}
|
||||
if (typeof params.imageHeight === "undefined") {
|
||||
params.imageHeight = "80px";
|
||||
}
|
||||
if (typeof params.imageUrl === "undefined" && typeof params.imageFA === "undefined") {
|
||||
params.imageUrl = null;
|
||||
} else if (typeof params.imageFA === "undefined") {
|
||||
image = "<img src='" + params.imageUrl.toString() + "' height='" + params.imageHeight.toString() + "' style='margin-bottom: 10px;'/><br />";
|
||||
} else if (typeof params.imageUrl === "undefined") {
|
||||
image = "<span class='bright " + "fa fa-" + params.imageFA + "' style='margin-bottom: 10px;font-size:" + params.imageHeight.toString() + ";'/></span><br />";
|
||||
}
|
||||
//Create overlay
|
||||
const overlay = document.createElement("div");
|
||||
overlay.id = "overlay";
|
||||
overlay.innerHTML += '<div class="black_overlay"></div>';
|
||||
document.body.insertBefore(overlay, document.body.firstChild);
|
||||
|
||||
//If module already has an open alert close it
|
||||
if (this.alerts[sender.name]) {
|
||||
this.hide_alert(sender, false);
|
||||
}
|
||||
|
||||
//Display title and message only if they are provided in notification parameters
|
||||
let message = "";
|
||||
if (params.title) {
|
||||
message += "<span class='light dimmed medium'>" + params.title + "</span>";
|
||||
}
|
||||
if (params.message) {
|
||||
if (message !== "") {
|
||||
message += "<br />";
|
||||
}
|
||||
|
||||
message += "<span class='thin bright small'>" + params.message + "</span>";
|
||||
}
|
||||
|
||||
//Store alert in this.alerts
|
||||
this.alerts[sender.name] = new NotificationFx({
|
||||
message: image + message,
|
||||
effect: this.config.alert_effect,
|
||||
ttl: params.timer,
|
||||
onClose: () => this.hide_alert(sender),
|
||||
al_no: "ns-alert"
|
||||
});
|
||||
|
||||
//Show alert
|
||||
this.alerts[sender.name].show();
|
||||
|
||||
//Add timer to dismiss alert and overlay
|
||||
if (params.timer) {
|
||||
setTimeout(() => {
|
||||
this.hide_alert(sender);
|
||||
}, params.timer);
|
||||
}
|
||||
},
|
||||
hide_alert: function (sender, close = true) {
|
||||
//Dismiss alert and remove from this.alerts
|
||||
if (this.alerts[sender.name]) {
|
||||
this.alerts[sender.name].dismiss(close);
|
||||
this.alerts[sender.name] = null;
|
||||
//Remove overlay
|
||||
const overlay = document.getElementById("overlay");
|
||||
overlay.parentNode.removeChild(overlay);
|
||||
}
|
||||
},
|
||||
setPosition: function (pos) {
|
||||
//Add css to body depending on the set position for notifications
|
||||
const sheet = document.createElement("style");
|
||||
if (pos === "center") {
|
||||
sheet.innerHTML = ".ns-box {margin-left: auto; margin-right: auto;text-align: center;}";
|
||||
}
|
||||
if (pos === "right") {
|
||||
sheet.innerHTML = ".ns-box {margin-left: auto;text-align: right;}";
|
||||
}
|
||||
if (pos === "left") {
|
||||
sheet.innerHTML = ".ns-box {margin-right: auto;text-align: left;}";
|
||||
}
|
||||
document.body.appendChild(sheet);
|
||||
},
|
||||
notificationReceived: function (notification, payload, sender) {
|
||||
if (notification === "SHOW_ALERT") {
|
||||
if (typeof payload.type === "undefined") {
|
||||
payload.type = "alert";
|
||||
}
|
||||
if (payload.type === "alert") {
|
||||
this.show_alert(payload, sender);
|
||||
} else if (payload.type === "notification") {
|
||||
this.show_notification(payload);
|
||||
}
|
||||
} else if (notification === "HIDE_ALERT") {
|
||||
this.hide_alert(sender);
|
||||
}
|
||||
},
|
||||
start: function () {
|
||||
this.alerts = {};
|
||||
this.setPosition(this.config.position);
|
||||
if (this.config.welcome_message) {
|
||||
if (this.config.welcome_message === true) {
|
||||
this.show_notification({ title: this.translate("sysTitle"), message: this.translate("welcome") });
|
||||
} else {
|
||||
this.show_notification({ title: this.translate("sysTitle"), message: this.config.welcome_message });
|
||||
}
|
||||
}
|
||||
Log.info("Starting module: " + this.name);
|
||||
}
|
||||
});
|
||||
932
modules/default/alert/notificationFx.css
Normal file
932
modules/default/alert/notificationFx.css
Normal file
@@ -0,0 +1,932 @@
|
||||
/* Based on work by https://tympanus.net/codrops/licensing/ */
|
||||
|
||||
.ns-box {
|
||||
background-color: rgba(0, 0, 0, 0.93);
|
||||
padding: 17px;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
z-index: 1;
|
||||
font-size: 70%;
|
||||
position: relative;
|
||||
display: table;
|
||||
word-wrap: break-word;
|
||||
max-width: 100%;
|
||||
border-width: 1px;
|
||||
border-radius: 5px;
|
||||
border-style: solid;
|
||||
border-color: var(--color-text-dimmed);
|
||||
}
|
||||
|
||||
.ns-alert {
|
||||
border-style: solid;
|
||||
border-color: var(--color-text-bright);
|
||||
padding: 17px;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 10px;
|
||||
z-index: 3;
|
||||
color: var(--color-text-bright);
|
||||
font-size: 70%;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
left: 0;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
top: 40%;
|
||||
width: 40%;
|
||||
height: auto;
|
||||
word-wrap: break-word;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.black_overlay {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
background-color: rgba(0, 0, 0, 0.93);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
[class^="ns-effect-"].ns-growl.ns-hide,
|
||||
[class*=" ns-effect-"].ns-growl.ns-hide {
|
||||
animation-direction: reverse;
|
||||
}
|
||||
|
||||
.ns-effect-flip {
|
||||
transform-origin: 50% 100%;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
.ns-effect-flip.ns-show,
|
||||
.ns-effect-flip.ns-hide {
|
||||
animation-name: animFlipFront;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
.ns-effect-flip.ns-hide {
|
||||
animation-name: animFlipBack;
|
||||
}
|
||||
|
||||
@keyframes animFlipFront {
|
||||
0% {
|
||||
transform: perspective(1000px) rotate3d(1, 0, 0, -90deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: perspective(1000px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animFlipBack {
|
||||
0% {
|
||||
transform: perspective(1000px) rotate3d(1, 0, 0, 90deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: perspective(1000px);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-bouncyflip.ns-show,
|
||||
.ns-effect-bouncyflip.ns-hide {
|
||||
animation-name: flipInX;
|
||||
animation-duration: 0.8s;
|
||||
}
|
||||
|
||||
@keyframes flipInX {
|
||||
0% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 20deg);
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -10deg);
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 5deg);
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-bouncyflip.ns-hide {
|
||||
animation-name: flipInXSimple;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
@keyframes flipInXSimple {
|
||||
0% {
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -90deg);
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-exploader {
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.ns-effect-exploader p {
|
||||
padding: 0.25em 2em 0.25em 3em;
|
||||
}
|
||||
|
||||
.ns-effect-exploader.ns-show {
|
||||
animation-name: animLoad;
|
||||
animation-duration: 1s;
|
||||
}
|
||||
|
||||
@keyframes animLoad {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale3d(0, 0.3, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-exploader.ns-hide {
|
||||
animation-name: animFade;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
.ns-effect-exploader.ns-show .ns-box-inner,
|
||||
.ns-effect-exploader.ns-show .ns-close {
|
||||
animation-fill-mode: both;
|
||||
animation-duration: 0.3s;
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
.ns-effect-exploader.ns-show .ns-close {
|
||||
animation-name: animFade;
|
||||
}
|
||||
|
||||
.ns-effect-exploader.ns-show .ns-box-inner {
|
||||
animation-name: animFadeMove;
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
@keyframes animFadeMove {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 10px, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animFade {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-scale.ns-show,
|
||||
.ns-effect-scale.ns-hide {
|
||||
animation-name: animScale;
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
@keyframes animScale {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 40px, 0) scale3d(0.1, 0.6, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-jelly.ns-show {
|
||||
animation-name: animJelly;
|
||||
animation-duration: 1s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
.ns-effect-jelly.ns-hide {
|
||||
animation-name: animFade;
|
||||
animation-duration: 0.3s;
|
||||
}
|
||||
|
||||
@keyframes animFade {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes animJelly {
|
||||
0% {
|
||||
transform: matrix3d(0.7, 0, 0, 0, 0, 0.7, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
2.083333% {
|
||||
transform: matrix3d(0.75266, 0, 0, 0, 0, 0.76342, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
4.166667% {
|
||||
transform: matrix3d(0.81071, 0, 0, 0, 0, 0.84545, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
6.25% {
|
||||
transform: matrix3d(0.86808, 0, 0, 0, 0, 0.9286, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
8.333333% {
|
||||
transform: matrix3d(0.92038, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
10.416667% {
|
||||
transform: matrix3d(0.96482, 0, 0, 0, 0, 1.05202, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
12.5% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1.08204, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
14.583333% {
|
||||
transform: matrix3d(1.02563, 0, 0, 0, 0, 1.09149, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
16.666667% {
|
||||
transform: matrix3d(1.04227, 0, 0, 0, 0, 1.08453, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
18.75% {
|
||||
transform: matrix3d(1.05102, 0, 0, 0, 0, 1.06666, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
20.833333% {
|
||||
transform: matrix3d(1.05334, 0, 0, 0, 0, 1.04355, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
22.916667% {
|
||||
transform: matrix3d(1.05078, 0, 0, 0, 0, 1.02012, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: matrix3d(1.04487, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
27.083333% {
|
||||
transform: matrix3d(1.03699, 0, 0, 0, 0, 0.98534, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
29.166667% {
|
||||
transform: matrix3d(1.02831, 0, 0, 0, 0, 0.97688, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
31.25% {
|
||||
transform: matrix3d(1.01973, 0, 0, 0, 0, 0.97422, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
33.333333% {
|
||||
transform: matrix3d(1.01191, 0, 0, 0, 0, 0.97618, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
35.416667% {
|
||||
transform: matrix3d(1.00526, 0, 0, 0, 0, 0.98122, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
37.5% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.98773, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
39.583333% {
|
||||
transform: matrix3d(0.99617, 0, 0, 0, 0, 0.99433, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
41.666667% {
|
||||
transform: matrix3d(0.99368, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
43.75% {
|
||||
transform: matrix3d(0.99237, 0, 0, 0, 0, 1.00413, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
45.833333% {
|
||||
transform: matrix3d(0.99202, 0, 0, 0, 0, 1.00651, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
47.916667% {
|
||||
transform: matrix3d(0.99241, 0, 0, 0, 0, 1.00726, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: matrix3d(0.99329, 0, 0, 0, 0, 1.00671, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
52.083333% {
|
||||
transform: matrix3d(0.99447, 0, 0, 0, 0, 1.00529, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
54.166667% {
|
||||
transform: matrix3d(0.99577, 0, 0, 0, 0, 1.00346, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
56.25% {
|
||||
transform: matrix3d(0.99705, 0, 0, 0, 0, 1.0016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
58.333333% {
|
||||
transform: matrix3d(0.99822, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
60.416667% {
|
||||
transform: matrix3d(0.99921, 0, 0, 0, 0, 0.99884, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
62.5% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.99816, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
64.583333% {
|
||||
transform: matrix3d(1.00057, 0, 0, 0, 0, 0.99795, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
66.666667% {
|
||||
transform: matrix3d(1.00095, 0, 0, 0, 0, 0.99811, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
68.75% {
|
||||
transform: matrix3d(1.00114, 0, 0, 0, 0, 0.99851, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
70.833333% {
|
||||
transform: matrix3d(1.00119, 0, 0, 0, 0, 0.99903, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
72.916667% {
|
||||
transform: matrix3d(1.00114, 0, 0, 0, 0, 0.99955, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: matrix3d(1.001, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
77.083333% {
|
||||
transform: matrix3d(1.00083, 0, 0, 0, 0, 1.00033, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
79.166667% {
|
||||
transform: matrix3d(1.00063, 0, 0, 0, 0, 1.00052, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
81.25% {
|
||||
transform: matrix3d(1.00044, 0, 0, 0, 0, 1.00058, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
83.333333% {
|
||||
transform: matrix3d(1.00027, 0, 0, 0, 0, 1.00053, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
85.416667% {
|
||||
transform: matrix3d(1.00012, 0, 0, 0, 0, 1.00042, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
87.5% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1.00027, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
89.583333% {
|
||||
transform: matrix3d(0.99991, 0, 0, 0, 0, 1.00013, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
91.666667% {
|
||||
transform: matrix3d(0.99986, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
93.75% {
|
||||
transform: matrix3d(0.99983, 0, 0, 0, 0, 0.99991, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
95.833333% {
|
||||
transform: matrix3d(0.99982, 0, 0, 0, 0, 0.99985, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
97.916667% {
|
||||
transform: matrix3d(0.99983, 0, 0, 0, 0, 0.99984, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-slide-left.ns-show {
|
||||
animation-name: animSlideElasticLeft;
|
||||
animation-duration: 1s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@keyframes animSlideElasticLeft {
|
||||
0% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1000, 0, 0, 1);
|
||||
}
|
||||
|
||||
1.666667% {
|
||||
transform: matrix3d(1.92933, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -739.26805, 0, 0, 1);
|
||||
}
|
||||
|
||||
3.333333% {
|
||||
transform: matrix3d(1.96989, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -521.82545, 0, 0, 1);
|
||||
}
|
||||
|
||||
5% {
|
||||
transform: matrix3d(1.70901, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -349.26115, 0, 0, 1);
|
||||
}
|
||||
|
||||
6.666667% {
|
||||
transform: matrix3d(1.4235, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -218.3238, 0, 0, 1);
|
||||
}
|
||||
|
||||
8.333333% {
|
||||
transform: matrix3d(1.21065, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -123.29848, 0, 0, 1);
|
||||
}
|
||||
|
||||
10% {
|
||||
transform: matrix3d(1.08167, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -57.59273, 0, 0, 1);
|
||||
}
|
||||
|
||||
11.666667% {
|
||||
transform: matrix3d(1.0165, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -14.72371, 0, 0, 1);
|
||||
}
|
||||
|
||||
13.333333% {
|
||||
transform: matrix3d(0.99057, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 11.12794, 0, 0, 1);
|
||||
}
|
||||
|
||||
15% {
|
||||
transform: matrix3d(0.98478, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 24.86339, 0, 0, 1);
|
||||
}
|
||||
|
||||
16.666667% {
|
||||
transform: matrix3d(0.98719, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 30.40503, 0, 0, 1);
|
||||
}
|
||||
|
||||
18.333333% {
|
||||
transform: matrix3d(0.9916, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 30.75275, 0, 0, 1);
|
||||
}
|
||||
|
||||
20% {
|
||||
transform: matrix3d(0.99541, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 28.10141, 0, 0, 1);
|
||||
}
|
||||
|
||||
21.666667% {
|
||||
transform: matrix3d(0.99795, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 23.98271, 0, 0, 1);
|
||||
}
|
||||
|
||||
23.333333% {
|
||||
transform: matrix3d(0.99936, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 19.40752, 0, 0, 1);
|
||||
}
|
||||
|
||||
25% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 14.99558, 0, 0, 1);
|
||||
}
|
||||
|
||||
26.666667% {
|
||||
transform: matrix3d(1.00021, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 11.08575, 0, 0, 1);
|
||||
}
|
||||
|
||||
28.333333% {
|
||||
transform: matrix3d(1.00022, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 7.82507, 0, 0, 1);
|
||||
}
|
||||
|
||||
30% {
|
||||
transform: matrix3d(1.00016, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 5.23737, 0, 0, 1);
|
||||
}
|
||||
|
||||
31.666667% {
|
||||
transform: matrix3d(1.0001, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3.27389, 0, 0, 1);
|
||||
}
|
||||
|
||||
33.333333% {
|
||||
transform: matrix3d(1.00005, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1.84893, 0, 0, 1);
|
||||
}
|
||||
|
||||
35% {
|
||||
transform: matrix3d(1.00002, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.86364, 0, 0, 1);
|
||||
}
|
||||
|
||||
36.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.22079, 0, 0, 1);
|
||||
}
|
||||
|
||||
38.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.16687, 0, 0, 1);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.37284, 0, 0, 1);
|
||||
}
|
||||
|
||||
41.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.45594, 0, 0, 1);
|
||||
}
|
||||
|
||||
43.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.46116, 0, 0, 1);
|
||||
}
|
||||
|
||||
45% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.4214, 0, 0, 1);
|
||||
}
|
||||
|
||||
46.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.35963, 0, 0, 1);
|
||||
}
|
||||
|
||||
48.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.29103, 0, 0, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.22487, 0, 0, 1);
|
||||
}
|
||||
|
||||
51.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.16624, 0, 0, 1);
|
||||
}
|
||||
|
||||
53.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.11734, 0, 0, 1);
|
||||
}
|
||||
|
||||
55% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.07854, 0, 0, 1);
|
||||
}
|
||||
|
||||
56.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.04909, 0, 0, 1);
|
||||
}
|
||||
|
||||
58.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.02773, 0, 0, 1);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.01295, 0, 0, 1);
|
||||
}
|
||||
|
||||
61.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.00331, 0, 0, 1);
|
||||
}
|
||||
|
||||
63.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.0025, 0, 0, 1);
|
||||
}
|
||||
|
||||
65% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00559, 0, 0, 1);
|
||||
}
|
||||
|
||||
66.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00684, 0, 0, 1);
|
||||
}
|
||||
|
||||
68.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00692, 0, 0, 1);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00632, 0, 0, 1);
|
||||
}
|
||||
|
||||
71.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00539, 0, 0, 1);
|
||||
}
|
||||
|
||||
73.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00436, 0, 0, 1);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00337, 0, 0, 1);
|
||||
}
|
||||
|
||||
76.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00249, 0, 0, 1);
|
||||
}
|
||||
|
||||
78.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00176, 0, 0, 1);
|
||||
}
|
||||
|
||||
80% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00118, 0, 0, 1);
|
||||
}
|
||||
|
||||
81.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00074, 0, 0, 1);
|
||||
}
|
||||
|
||||
83.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00042, 0, 0, 1);
|
||||
}
|
||||
|
||||
85% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00019, 0, 0, 1);
|
||||
}
|
||||
|
||||
86.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.00005, 0, 0, 1);
|
||||
}
|
||||
|
||||
88.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.00004, 0, 0, 1);
|
||||
}
|
||||
|
||||
90% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.00008, 0, 0, 1);
|
||||
}
|
||||
|
||||
91.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.0001, 0, 0, 1);
|
||||
}
|
||||
|
||||
93.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.0001, 0, 0, 1);
|
||||
}
|
||||
|
||||
95% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.00009, 0, 0, 1);
|
||||
}
|
||||
|
||||
96.666667% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.00008, 0, 0, 1);
|
||||
}
|
||||
|
||||
98.333333% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.00007, 0, 0, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-slide-left.ns-hide {
|
||||
animation-name: animSlideLeft;
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
@keyframes animSlideLeft {
|
||||
0% {
|
||||
transform: translate3d(-30px, 0, 0) translate3d(-100%, 0, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-slide-right.ns-show {
|
||||
animation: animSlideElasticRight 2000ms linear both;
|
||||
}
|
||||
|
||||
@keyframes animSlideElasticRight {
|
||||
0% {
|
||||
transform: matrix3d(2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1000, 0, 0, 1);
|
||||
}
|
||||
|
||||
2.15% {
|
||||
transform: matrix3d(1.486, 0, 0, 0, 0, 0.514, 0, 0, 0, 0, 1, 0, 664.594, 0, 0, 1);
|
||||
}
|
||||
|
||||
4.1% {
|
||||
transform: matrix3d(1.147, 0, 0, 0, 0, 0.853, 0, 0, 0, 0, 1, 0, 419.708, 0, 0, 1);
|
||||
}
|
||||
|
||||
4.3% {
|
||||
transform: matrix3d(1.121, 0, 0, 0, 0, 0.879, 0, 0, 0, 0, 1, 0, 398.136, 0, 0, 1);
|
||||
}
|
||||
|
||||
6.46% {
|
||||
transform: matrix3d(0.948, 0, 0, 0, 0, 1.052, 0, 0, 0, 0, 1, 0, 206.714, 0, 0, 1);
|
||||
}
|
||||
|
||||
8.11% {
|
||||
transform: matrix3d(0.908, 0, 0, 0, 0, 1.092, 0, 0, 0, 0, 1, 0, 105.491, 0, 0, 1);
|
||||
}
|
||||
|
||||
8.61% {
|
||||
transform: matrix3d(0.907, 0, 0, 0, 0, 1.093, 0, 0, 0, 0, 1, 0, 81.572, 0, 0, 1);
|
||||
}
|
||||
|
||||
12.11% {
|
||||
transform: matrix3d(0.95, 0, 0, 0, 0, 1.05, 0, 0, 0, 0, 1, 0, -18.434, 0, 0, 1);
|
||||
}
|
||||
|
||||
14.16% {
|
||||
transform: matrix3d(0.979, 0, 0, 0, 0, 1.021, 0, 0, 0, 0, 1, 0, -38.734, 0, 0, 1);
|
||||
}
|
||||
|
||||
16.12% {
|
||||
transform: matrix3d(0.997, 0, 0, 0, 0, 1.003, 0, 0, 0, 0, 1, 0, -43.356, 0, 0, 1);
|
||||
}
|
||||
|
||||
19.72% {
|
||||
transform: matrix3d(1.006, 0, 0, 0, 0, 0.994, 0, 0, 0, 0, 1, 0, -34.155, 0, 0, 1);
|
||||
}
|
||||
|
||||
27.23% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -7.839, 0, 0, 1);
|
||||
}
|
||||
|
||||
30.83% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -1.951, 0, 0, 1);
|
||||
}
|
||||
|
||||
38.34% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1.037, 0, 0, 1);
|
||||
}
|
||||
|
||||
41.99% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.812, 0, 0, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.159, 0, 0, 1);
|
||||
}
|
||||
|
||||
60.56% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, -0.025, 0, 0, 1);
|
||||
}
|
||||
|
||||
82.78% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0.001, 0, 0, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-slide-right.ns-hide {
|
||||
animation-name: animSlideRight;
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
@keyframes animSlideRight {
|
||||
0% {
|
||||
transform: translate3d(30px, 0, 0) translate3d(100%, 0, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-slide-center.ns-show {
|
||||
animation: animSlideElasticCenter 2000ms linear both;
|
||||
}
|
||||
|
||||
@keyframes animSlideElasticCenter {
|
||||
0% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, -300, 0, 1);
|
||||
}
|
||||
|
||||
2.15% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1.971, 0, 0, 0, 0, 1, 0, 0, -199.378, 0, 1);
|
||||
}
|
||||
|
||||
4.1% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1.294, 0, 0, 0, 0, 1, 0, 0, -125.912, 0, 1);
|
||||
}
|
||||
|
||||
4.3% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1.243, 0, 0, 0, 0, 1, 0, 0, -119.441, 0, 1);
|
||||
}
|
||||
|
||||
6.46% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.895, 0, 0, 0, 0, 1, 0, 0, -62.014, 0, 1);
|
||||
}
|
||||
|
||||
8.11% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.817, 0, 0, 0, 0, 1, 0, 0, -31.647, 0, 1);
|
||||
}
|
||||
|
||||
8.61% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.813, 0, 0, 0, 0, 1, 0, 0, -24.472, 0, 1);
|
||||
}
|
||||
|
||||
12.11% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.9, 0, 0, 0, 0, 1, 0, 0, 5.53, 0, 1);
|
||||
}
|
||||
|
||||
14.16% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.959, 0, 0, 0, 0, 1, 0, 0, 11.62, 0, 1);
|
||||
}
|
||||
|
||||
16.12% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.994, 0, 0, 0, 0, 1, 0, 0, 13.007, 0, 1);
|
||||
}
|
||||
|
||||
19.72% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1.012, 0, 0, 0, 0, 1, 0, 0, 10.247, 0, 1);
|
||||
}
|
||||
|
||||
27.23% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2.352, 0, 1);
|
||||
}
|
||||
|
||||
30.83% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 0.999, 0, 0, 0, 0, 1, 0, 0, 0.585, 0, 1);
|
||||
}
|
||||
|
||||
38.34% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -0.311, 0, 1);
|
||||
}
|
||||
|
||||
41.99% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -0.244, 0, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, -0.048, 0, 1);
|
||||
}
|
||||
|
||||
60.56% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0.007, 0, 1);
|
||||
}
|
||||
|
||||
82.78% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-slide-center.ns-hide {
|
||||
animation-name: animSlideCenter;
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
@keyframes animSlideCenter {
|
||||
0% {
|
||||
transform: translate3d(0, -30px, 0) translate3d(0, -100%, 0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.ns-effect-genie.ns-show,
|
||||
.ns-effect-genie.ns-hide {
|
||||
animation-name: animGenie;
|
||||
animation-duration: 0.4s;
|
||||
}
|
||||
|
||||
@keyframes animGenie {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, calc(200% + 30px), 0) scale3d(0, 1, 1);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
|
||||
40% {
|
||||
opacity: 0.5;
|
||||
transform: translate3d(0, 0, 0) scale3d(0.02, 1.1, 1);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
70% {
|
||||
opacity: 0.6;
|
||||
transform: translate3d(0, -40px, 0) scale3d(0.8, 1.1, 1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0) scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
158
modules/default/alert/notificationFx.js
Normal file
158
modules/default/alert/notificationFx.js
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Based on work by
|
||||
*
|
||||
* notificationFx.js v1.0.0
|
||||
* https://tympanus.net/codrops/
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
* https://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Copyright 2014, Codrops
|
||||
* https://tympanus.net/codrops/
|
||||
*/
|
||||
(function (window) {
|
||||
/**
|
||||
* Extend one object with another one
|
||||
*
|
||||
* @param {object} a The object to extend
|
||||
* @param {object} b The object which extends the other, overwrites existing keys
|
||||
* @returns {object} The merged object
|
||||
*/
|
||||
function extend(a, b) {
|
||||
for (let key in b) {
|
||||
if (b.hasOwnProperty(key)) {
|
||||
a[key] = b[key];
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* NotificationFx constructor
|
||||
*
|
||||
* @param {object} options The configuration options
|
||||
* @class
|
||||
*/
|
||||
function NotificationFx(options) {
|
||||
this.options = extend({}, this.options);
|
||||
extend(this.options, options);
|
||||
this._init();
|
||||
}
|
||||
|
||||
/**
|
||||
* NotificationFx options
|
||||
*/
|
||||
NotificationFx.prototype.options = {
|
||||
// element to which the notification will be appended
|
||||
// defaults to the document.body
|
||||
wrapper: document.body,
|
||||
// the message
|
||||
message: "yo!",
|
||||
// layout type: growl|attached|bar|other
|
||||
layout: "growl",
|
||||
// effects for the specified layout:
|
||||
// for growl layout: scale|slide|genie|jelly
|
||||
// for attached layout: flip|bouncyflip
|
||||
// for other layout: boxspinner|cornerexpand|loadingcircle|thumbslider
|
||||
// ...
|
||||
effect: "slide",
|
||||
// notice, warning, error, success
|
||||
// will add class ns-type-warning, ns-type-error or ns-type-success
|
||||
type: "notice",
|
||||
// if the user doesn´t close the notification then we remove it
|
||||
// after the following time
|
||||
ttl: 6000,
|
||||
al_no: "ns-box",
|
||||
// callbacks
|
||||
onClose: function () {
|
||||
return false;
|
||||
},
|
||||
onOpen: function () {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize and cache some vars
|
||||
*/
|
||||
NotificationFx.prototype._init = function () {
|
||||
// create HTML structure
|
||||
this.ntf = document.createElement("div");
|
||||
this.ntf.className = this.options.al_no + " ns-" + this.options.layout + " ns-effect-" + this.options.effect + " ns-type-" + this.options.type;
|
||||
let strinner = '<div class="ns-box-inner">';
|
||||
strinner += this.options.message;
|
||||
strinner += "</div>";
|
||||
this.ntf.innerHTML = strinner;
|
||||
|
||||
// append to body or the element specified in options.wrapper
|
||||
this.options.wrapper.insertBefore(this.ntf, this.options.wrapper.nextSibling);
|
||||
|
||||
// dismiss after [options.ttl]ms
|
||||
if (this.options.ttl) {
|
||||
this.dismissttl = setTimeout(() => {
|
||||
if (this.active) {
|
||||
this.dismiss();
|
||||
}
|
||||
}, this.options.ttl);
|
||||
}
|
||||
|
||||
// init events
|
||||
this._initEvents();
|
||||
};
|
||||
|
||||
/**
|
||||
* Init events
|
||||
*/
|
||||
NotificationFx.prototype._initEvents = function () {
|
||||
// dismiss notification by tapping on it if someone has a touchscreen
|
||||
this.ntf.querySelector(".ns-box-inner").addEventListener("click", () => {
|
||||
this.dismiss();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the notification
|
||||
*/
|
||||
NotificationFx.prototype.show = function () {
|
||||
this.active = true;
|
||||
this.ntf.classList.remove("ns-hide");
|
||||
this.ntf.classList.add("ns-show");
|
||||
this.options.onOpen();
|
||||
};
|
||||
|
||||
/**
|
||||
* Dismiss the notification
|
||||
*
|
||||
* @param {boolean} [close] call the onClose callback at the end
|
||||
*/
|
||||
NotificationFx.prototype.dismiss = function (close = true) {
|
||||
this.active = false;
|
||||
clearTimeout(this.dismissttl);
|
||||
this.ntf.classList.remove("ns-show");
|
||||
setTimeout(() => {
|
||||
this.ntf.classList.add("ns-hide");
|
||||
|
||||
// callback
|
||||
if (close) this.options.onClose();
|
||||
}, 25);
|
||||
|
||||
// after animation ends remove ntf from the DOM
|
||||
const onEndAnimationFn = (ev) => {
|
||||
if (ev.target !== this.ntf) {
|
||||
return false;
|
||||
}
|
||||
this.ntf.removeEventListener("animationend", onEndAnimationFn);
|
||||
|
||||
if (ev.target.parentNode === this.options.wrapper) {
|
||||
this.options.wrapper.removeChild(this.ntf);
|
||||
}
|
||||
};
|
||||
|
||||
this.ntf.addEventListener("animationend", onEndAnimationFn);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add to global namespace
|
||||
*/
|
||||
window.NotificationFx = NotificationFx;
|
||||
})(window);
|
||||
4
modules/default/alert/translations/bg.json
Normal file
4
modules/default/alert/translations/bg.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror нотификация",
|
||||
"welcome": "Добре дошли, стартирането беше успешно"
|
||||
}
|
||||
4
modules/default/alert/translations/da.json
Normal file
4
modules/default/alert/translations/da.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Notifikation",
|
||||
"welcome": "Velkommen, modulet er succesfuldt startet!"
|
||||
}
|
||||
4
modules/default/alert/translations/de.json
Normal file
4
modules/default/alert/translations/de.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Benachrichtigung",
|
||||
"welcome": "Willkommen, Start war erfolgreich!"
|
||||
}
|
||||
4
modules/default/alert/translations/en.json
Normal file
4
modules/default/alert/translations/en.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Notification",
|
||||
"welcome": "Welcome, start was successful!"
|
||||
}
|
||||
4
modules/default/alert/translations/es.json
Normal file
4
modules/default/alert/translations/es.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Notificaciones",
|
||||
"welcome": "Bienvenido, ¡se iniciado correctamente!"
|
||||
}
|
||||
4
modules/default/alert/translations/fr.json
Normal file
4
modules/default/alert/translations/fr.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Notification",
|
||||
"welcome": "Bienvenue, le démarrage a été un succès!"
|
||||
}
|
||||
4
modules/default/alert/translations/hu.json
Normal file
4
modules/default/alert/translations/hu.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror értesítés",
|
||||
"welcome": "Üdvözöljük, indulás sikeres!"
|
||||
}
|
||||
4
modules/default/alert/translations/nl.json
Normal file
4
modules/default/alert/translations/nl.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Notificatie",
|
||||
"welcome": "Welkom, Succesvol gestart!"
|
||||
}
|
||||
4
modules/default/alert/translations/ru.json
Normal file
4
modules/default/alert/translations/ru.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"sysTitle": "MagicMirror Уведомление",
|
||||
"welcome": "Добро пожаловать, старт был успешным!"
|
||||
}
|
||||
6
modules/default/calendar/README.md
Executable file
6
modules/default/calendar/README.md
Executable file
@@ -0,0 +1,6 @@
|
||||
# Module: Calendar
|
||||
|
||||
The `calendar` module is one of the default modules of the MagicMirror.
|
||||
This module displays events from a public .ical calendar. It can combine multiple calendars.
|
||||
|
||||
For configuration options, please check the [MagicMirror² documentation](https://docs.magicmirror.builders/modules/calendar.html).
|
||||
23
modules/default/calendar/calendar.css
Normal file
23
modules/default/calendar/calendar.css
Normal file
@@ -0,0 +1,23 @@
|
||||
.calendar .symbol {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
.calendar .symbol span {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.calendar .title {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.calendar .time {
|
||||
padding-left: 30px;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
}
|
||||
846
modules/default/calendar/calendar.js
Executable file
846
modules/default/calendar/calendar.js
Executable file
@@ -0,0 +1,846 @@
|
||||
/* global cloneObject */
|
||||
|
||||
/* Magic Mirror
|
||||
* Module: Calendar
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
Module.register("calendar", {
|
||||
// Define module defaults
|
||||
defaults: {
|
||||
maximumEntries: 10, // Total Maximum Entries
|
||||
maximumNumberOfDays: 365,
|
||||
limitDays: 0, // Limit the number of days shown, 0 = no limit
|
||||
displaySymbol: true,
|
||||
defaultSymbol: "calendar", // Fontawesome Symbol see https://fontawesome.com/cheatsheet?from=io
|
||||
showLocation: false,
|
||||
displayRepeatingCountTitle: false,
|
||||
defaultRepeatingCountTitle: "",
|
||||
maxTitleLength: 25,
|
||||
maxLocationTitleLength: 25,
|
||||
wrapEvents: false, // wrap events to multiple lines breaking at maxTitleLength
|
||||
wrapLocationEvents: false,
|
||||
maxTitleLines: 3,
|
||||
maxEventTitleLines: 3,
|
||||
fetchInterval: 5 * 60 * 1000, // Update every 5 minutes.
|
||||
animationSpeed: 2000,
|
||||
fade: true,
|
||||
urgency: 7,
|
||||
timeFormat: "relative",
|
||||
dateFormat: "MMM Do",
|
||||
dateEndFormat: "LT",
|
||||
fullDayEventDateFormat: "MMM Do",
|
||||
showEnd: false,
|
||||
getRelative: 6,
|
||||
fadePoint: 0.25, // Start on 1/4th of the list.
|
||||
hidePrivate: false,
|
||||
hideOngoing: false,
|
||||
hideTime: false,
|
||||
colored: false,
|
||||
coloredSymbolOnly: false,
|
||||
customEvents: [], // Array of {keyword: "", symbol: "", color: ""} where Keyword is a regexp and symbol/color are to be applied for matched
|
||||
tableClass: "small",
|
||||
calendars: [
|
||||
{
|
||||
symbol: "calendar",
|
||||
url: "https://www.calendarlabs.com/templates/ical/US-Holidays.ics"
|
||||
}
|
||||
],
|
||||
titleReplace: {
|
||||
"De verjaardag van ": "",
|
||||
"'s birthday": ""
|
||||
},
|
||||
locationTitleReplace: {
|
||||
"street ": ""
|
||||
},
|
||||
broadcastEvents: true,
|
||||
excludedEvents: [],
|
||||
sliceMultiDayEvents: false,
|
||||
broadcastPastEvents: false,
|
||||
nextDaysRelative: false,
|
||||
selfSignedCert: false
|
||||
},
|
||||
|
||||
requiresVersion: "2.1.0",
|
||||
|
||||
// Define required scripts.
|
||||
getStyles: function () {
|
||||
return ["calendar.css", "font-awesome.css"];
|
||||
},
|
||||
|
||||
// Define required scripts.
|
||||
getScripts: function () {
|
||||
return ["moment.js"];
|
||||
},
|
||||
|
||||
// Define required translations.
|
||||
getTranslations: function () {
|
||||
// The translations for the default modules are defined in the core translation files.
|
||||
// Therefore we can just return false. Otherwise we should have returned a dictionary.
|
||||
// If you're trying to build your own module including translations, check out the documentation.
|
||||
return false;
|
||||
},
|
||||
|
||||
// Override start method.
|
||||
start: function () {
|
||||
Log.info("Starting module: " + this.name);
|
||||
|
||||
// Set locale.
|
||||
moment.updateLocale(config.language, this.getLocaleSpecification(config.timeFormat));
|
||||
|
||||
// clear data holder before start
|
||||
this.calendarData = {};
|
||||
|
||||
// indicate no data available yet
|
||||
this.loaded = false;
|
||||
|
||||
this.config.calendars.forEach((calendar) => {
|
||||
calendar.url = calendar.url.replace("webcal://", "http://");
|
||||
|
||||
const calendarConfig = {
|
||||
maximumEntries: calendar.maximumEntries,
|
||||
maximumNumberOfDays: calendar.maximumNumberOfDays,
|
||||
broadcastPastEvents: calendar.broadcastPastEvents,
|
||||
selfSignedCert: calendar.selfSignedCert
|
||||
};
|
||||
|
||||
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
|
||||
calendarConfig.symbolClass = "";
|
||||
}
|
||||
if (calendar.titleClass === "undefined" || calendar.titleClass === null) {
|
||||
calendarConfig.titleClass = "";
|
||||
}
|
||||
if (calendar.timeClass === "undefined" || calendar.timeClass === null) {
|
||||
calendarConfig.timeClass = "";
|
||||
}
|
||||
|
||||
// we check user and password here for backwards compatibility with old configs
|
||||
if (calendar.user && calendar.pass) {
|
||||
Log.warn("Deprecation warning: Please update your calendar authentication configuration.");
|
||||
Log.warn("https://github.com/MichMich/MagicMirror/tree/v2.1.2/modules/default/calendar#calendar-authentication-options");
|
||||
calendar.auth = {
|
||||
user: calendar.user,
|
||||
pass: calendar.pass
|
||||
};
|
||||
}
|
||||
|
||||
// tell helper to start a fetcher for this calendar
|
||||
// fetcher till cycle
|
||||
this.addCalendar(calendar.url, calendar.auth, calendarConfig);
|
||||
});
|
||||
},
|
||||
|
||||
// Override socket notification handler.
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
if (this.identifier !== payload.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (notification === "CALENDAR_EVENTS") {
|
||||
if (this.hasCalendarURL(payload.url)) {
|
||||
this.calendarData[payload.url] = payload.events;
|
||||
this.error = null;
|
||||
this.loaded = true;
|
||||
|
||||
if (this.config.broadcastEvents) {
|
||||
this.broadcastEvents();
|
||||
}
|
||||
}
|
||||
} else if (notification === "CALENDAR_ERROR") {
|
||||
let error_message = this.translate(payload.error_type);
|
||||
this.error = this.translate("MODULE_CONFIG_ERROR", { MODULE_NAME: this.name, ERROR: error_message });
|
||||
this.loaded = true;
|
||||
}
|
||||
|
||||
this.updateDom(this.config.animationSpeed);
|
||||
},
|
||||
|
||||
// Override dom generator.
|
||||
getDom: function () {
|
||||
// Define second, minute, hour, and day constants
|
||||
const oneSecond = 1000; // 1,000 milliseconds
|
||||
const oneMinute = oneSecond * 60;
|
||||
const oneHour = oneMinute * 60;
|
||||
const oneDay = oneHour * 24;
|
||||
|
||||
const events = this.createEventList();
|
||||
const wrapper = document.createElement("table");
|
||||
wrapper.className = this.config.tableClass;
|
||||
|
||||
if (this.error) {
|
||||
wrapper.innerHTML = this.error;
|
||||
wrapper.className = this.config.tableClass + " dimmed";
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
if (events.length === 0) {
|
||||
wrapper.innerHTML = this.loaded ? this.translate("EMPTY") : this.translate("LOADING");
|
||||
wrapper.className = this.config.tableClass + " dimmed";
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
let currentFadeStep = 0;
|
||||
let startFade;
|
||||
let fadeSteps;
|
||||
|
||||
if (this.config.fade && this.config.fadePoint < 1) {
|
||||
if (this.config.fadePoint < 0) {
|
||||
this.config.fadePoint = 0;
|
||||
}
|
||||
startFade = events.length * this.config.fadePoint;
|
||||
fadeSteps = events.length - startFade;
|
||||
}
|
||||
|
||||
let lastSeenDate = "";
|
||||
|
||||
events.forEach((event, index) => {
|
||||
const dateAsString = moment(event.startDate, "x").format(this.config.dateFormat);
|
||||
if (this.config.timeFormat === "dateheaders") {
|
||||
if (lastSeenDate !== dateAsString) {
|
||||
const dateRow = document.createElement("tr");
|
||||
dateRow.className = "normal";
|
||||
|
||||
const dateCell = document.createElement("td");
|
||||
dateCell.colSpan = "3";
|
||||
dateCell.innerHTML = dateAsString;
|
||||
dateCell.style.paddingTop = "10px";
|
||||
dateRow.appendChild(dateCell);
|
||||
wrapper.appendChild(dateRow);
|
||||
|
||||
if (this.config.fade && index >= startFade) {
|
||||
//fading
|
||||
currentFadeStep = index - startFade;
|
||||
dateRow.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
|
||||
}
|
||||
|
||||
lastSeenDate = dateAsString;
|
||||
}
|
||||
}
|
||||
|
||||
const eventWrapper = document.createElement("tr");
|
||||
|
||||
if (this.config.colored && !this.config.coloredSymbolOnly) {
|
||||
eventWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
|
||||
}
|
||||
|
||||
eventWrapper.className = "normal event";
|
||||
|
||||
const symbolWrapper = document.createElement("td");
|
||||
|
||||
if (this.config.displaySymbol) {
|
||||
if (this.config.colored && this.config.coloredSymbolOnly) {
|
||||
symbolWrapper.style.cssText = "color:" + this.colorForUrl(event.url);
|
||||
}
|
||||
|
||||
const symbolClass = this.symbolClassForUrl(event.url);
|
||||
symbolWrapper.className = "symbol align-right " + symbolClass;
|
||||
|
||||
const symbols = this.symbolsForEvent(event);
|
||||
// If symbols are displayed and custom symbol is set, replace event symbol
|
||||
if (this.config.displaySymbol && this.config.customEvents.length > 0) {
|
||||
for (let ev in this.config.customEvents) {
|
||||
if (typeof this.config.customEvents[ev].symbol !== "undefined" && this.config.customEvents[ev].symbol !== "") {
|
||||
let needle = new RegExp(this.config.customEvents[ev].keyword, "gi");
|
||||
if (needle.test(event.title)) {
|
||||
symbols[0] = this.config.customEvents[ev].symbol;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
symbols.forEach((s, index) => {
|
||||
const symbol = document.createElement("span");
|
||||
symbol.className = "fa fa-fw fa-" + s;
|
||||
if (index > 0) {
|
||||
symbol.style.paddingLeft = "5px";
|
||||
}
|
||||
symbolWrapper.appendChild(symbol);
|
||||
});
|
||||
eventWrapper.appendChild(symbolWrapper);
|
||||
} else if (this.config.timeFormat === "dateheaders") {
|
||||
const blankCell = document.createElement("td");
|
||||
blankCell.innerHTML = " ";
|
||||
eventWrapper.appendChild(blankCell);
|
||||
}
|
||||
|
||||
const titleWrapper = document.createElement("td");
|
||||
let repeatingCountTitle = "";
|
||||
|
||||
if (this.config.displayRepeatingCountTitle && event.firstYear !== undefined) {
|
||||
repeatingCountTitle = this.countTitleForUrl(event.url);
|
||||
|
||||
if (repeatingCountTitle !== "") {
|
||||
const thisYear = new Date(parseInt(event.startDate)).getFullYear(),
|
||||
yearDiff = thisYear - event.firstYear;
|
||||
|
||||
repeatingCountTitle = ", " + yearDiff + ". " + repeatingCountTitle;
|
||||
}
|
||||
}
|
||||
|
||||
// Color events if custom color is specified
|
||||
if (this.config.customEvents.length > 0) {
|
||||
for (let ev in this.config.customEvents) {
|
||||
if (typeof this.config.customEvents[ev].color !== "undefined" && this.config.customEvents[ev].color !== "") {
|
||||
let needle = new RegExp(this.config.customEvents[ev].keyword, "gi");
|
||||
if (needle.test(event.title)) {
|
||||
// Respect parameter ColoredSymbolOnly also for custom events
|
||||
if (!this.config.coloredSymbolOnly) {
|
||||
eventWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
||||
titleWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
||||
}
|
||||
if (this.config.displaySymbol) {
|
||||
symbolWrapper.style.cssText = "color:" + this.config.customEvents[ev].color;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
titleWrapper.innerHTML = this.titleTransform(event.title, this.config.titleReplace, this.config.wrapEvents, this.config.maxTitleLength, this.config.maxTitleLines) + repeatingCountTitle;
|
||||
|
||||
const titleClass = this.titleClassForUrl(event.url);
|
||||
|
||||
if (!this.config.colored) {
|
||||
titleWrapper.className = "title bright " + titleClass;
|
||||
} else {
|
||||
titleWrapper.className = "title " + titleClass;
|
||||
}
|
||||
|
||||
if (this.config.timeFormat === "dateheaders") {
|
||||
if (event.fullDayEvent) {
|
||||
titleWrapper.colSpan = "2";
|
||||
titleWrapper.classList.add("align-left");
|
||||
} else {
|
||||
const timeWrapper = document.createElement("td");
|
||||
timeWrapper.className = "time light align-left " + this.timeClassForUrl(event.url);
|
||||
timeWrapper.style.paddingLeft = "2px";
|
||||
timeWrapper.innerHTML = moment(event.startDate, "x").format("LT");
|
||||
eventWrapper.appendChild(timeWrapper);
|
||||
titleWrapper.classList.add("align-right");
|
||||
}
|
||||
|
||||
eventWrapper.appendChild(titleWrapper);
|
||||
} else {
|
||||
const timeWrapper = document.createElement("td");
|
||||
|
||||
eventWrapper.appendChild(titleWrapper);
|
||||
const now = new Date();
|
||||
|
||||
if (this.config.timeFormat === "absolute") {
|
||||
// Use dateFormat
|
||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.dateFormat));
|
||||
// Add end time if showEnd
|
||||
if (this.config.showEnd) {
|
||||
timeWrapper.innerHTML += "-";
|
||||
timeWrapper.innerHTML += this.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat));
|
||||
}
|
||||
// For full day events we use the fullDayEventDateFormat
|
||||
if (event.fullDayEvent) {
|
||||
//subtract one second so that fullDayEvents end at 23:59:59, and not at 0:00:00 one the next day
|
||||
event.endDate -= oneSecond;
|
||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").format(this.config.fullDayEventDateFormat));
|
||||
}
|
||||
if (this.config.getRelative > 0 && event.startDate < now) {
|
||||
// Ongoing and getRelative is set
|
||||
timeWrapper.innerHTML = this.capFirst(
|
||||
this.translate("RUNNING", {
|
||||
fallback: this.translate("RUNNING") + " {timeUntilEnd}",
|
||||
timeUntilEnd: moment(event.endDate, "x").fromNow(true)
|
||||
})
|
||||
);
|
||||
} else if (this.config.urgency > 0 && event.startDate - now < this.config.urgency * oneDay) {
|
||||
// Within urgency days
|
||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
||||
}
|
||||
if (event.fullDayEvent && this.config.nextDaysRelative) {
|
||||
// Full days events within the next two days
|
||||
if (event.today) {
|
||||
timeWrapper.innerHTML = this.capFirst(this.translate("TODAY"));
|
||||
} else if (event.startDate - now < oneDay && event.startDate - now > 0) {
|
||||
timeWrapper.innerHTML = this.capFirst(this.translate("TOMORROW"));
|
||||
} else if (event.startDate - now < 2 * oneDay && event.startDate - now > 0) {
|
||||
if (this.translate("DAYAFTERTOMORROW") !== "DAYAFTERTOMORROW") {
|
||||
timeWrapper.innerHTML = this.capFirst(this.translate("DAYAFTERTOMORROW"));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Show relative times
|
||||
if (event.startDate >= now) {
|
||||
// Use relative time
|
||||
if (!this.config.hideTime) {
|
||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").calendar(null, { sameElse: this.config.dateFormat }));
|
||||
} else {
|
||||
timeWrapper.innerHTML = this.capFirst(
|
||||
moment(event.startDate, "x").calendar(null, {
|
||||
sameDay: "[" + this.translate("TODAY") + "]",
|
||||
nextDay: "[" + this.translate("TOMORROW") + "]",
|
||||
nextWeek: "dddd",
|
||||
sameElse: this.config.dateFormat
|
||||
})
|
||||
);
|
||||
}
|
||||
if (event.startDate - now < this.config.getRelative * oneHour) {
|
||||
// If event is within getRelative hours, display 'in xxx' time format or moment.fromNow()
|
||||
timeWrapper.innerHTML = this.capFirst(moment(event.startDate, "x").fromNow());
|
||||
}
|
||||
} else {
|
||||
// Ongoing event
|
||||
timeWrapper.innerHTML = this.capFirst(
|
||||
this.translate("RUNNING", {
|
||||
fallback: this.translate("RUNNING") + " {timeUntilEnd}",
|
||||
timeUntilEnd: moment(event.endDate, "x").fromNow(true)
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
timeWrapper.className = "time light " + this.timeClassForUrl(event.url);
|
||||
eventWrapper.appendChild(timeWrapper);
|
||||
}
|
||||
|
||||
wrapper.appendChild(eventWrapper);
|
||||
|
||||
// Create fade effect.
|
||||
if (index >= startFade) {
|
||||
currentFadeStep = index - startFade;
|
||||
eventWrapper.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
|
||||
}
|
||||
|
||||
if (this.config.showLocation) {
|
||||
if (event.location !== false) {
|
||||
const locationRow = document.createElement("tr");
|
||||
locationRow.className = "normal xsmall light";
|
||||
|
||||
if (this.config.displaySymbol) {
|
||||
const symbolCell = document.createElement("td");
|
||||
locationRow.appendChild(symbolCell);
|
||||
}
|
||||
|
||||
const descCell = document.createElement("td");
|
||||
descCell.className = "location";
|
||||
descCell.colSpan = "2";
|
||||
descCell.innerHTML = this.titleTransform(event.location, this.config.locationTitleReplace, this.config.wrapLocationEvents, this.config.maxLocationTitleLength, this.config.maxEventTitleLines);
|
||||
locationRow.appendChild(descCell);
|
||||
|
||||
wrapper.appendChild(locationRow);
|
||||
|
||||
if (index >= startFade) {
|
||||
currentFadeStep = index - startFade;
|
||||
locationRow.style.opacity = 1 - (1 / fadeSteps) * currentFadeStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return wrapper;
|
||||
},
|
||||
|
||||
/**
|
||||
* This function accepts a number (either 12 or 24) and returns a moment.js LocaleSpecification with the
|
||||
* corresponding timeformat to be used in the calendar display. If no number is given (or otherwise invalid input)
|
||||
* it will a localeSpecification object with the system locale time format.
|
||||
*
|
||||
* @param {number} timeFormat Specifies either 12 or 24 hour time format
|
||||
* @returns {moment.LocaleSpecification} formatted time
|
||||
*/
|
||||
getLocaleSpecification: function (timeFormat) {
|
||||
switch (timeFormat) {
|
||||
case 12: {
|
||||
return { longDateFormat: { LT: "h:mm A" } };
|
||||
}
|
||||
case 24: {
|
||||
return { longDateFormat: { LT: "HH:mm" } };
|
||||
}
|
||||
default: {
|
||||
return { longDateFormat: { LT: moment.localeData().longDateFormat("LT") } };
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if this config contains the calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {boolean} True if the calendar config contains the url, False otherwise
|
||||
*/
|
||||
hasCalendarURL: function (url) {
|
||||
for (const calendar of this.config.calendars) {
|
||||
if (calendar.url === url) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the sorted list of all events.
|
||||
*
|
||||
* @returns {object[]} Array with events.
|
||||
*/
|
||||
createEventList: function () {
|
||||
const now = new Date();
|
||||
const today = moment().startOf("day");
|
||||
const future = moment().startOf("day").add(this.config.maximumNumberOfDays, "days").toDate();
|
||||
let events = [];
|
||||
|
||||
for (const calendarUrl in this.calendarData) {
|
||||
const calendar = this.calendarData[calendarUrl];
|
||||
for (const e in calendar) {
|
||||
const event = JSON.parse(JSON.stringify(calendar[e])); // clone object
|
||||
|
||||
if (event.endDate < now) {
|
||||
continue;
|
||||
}
|
||||
if (this.config.hidePrivate) {
|
||||
if (event.class === "PRIVATE") {
|
||||
// do not add the current event, skip it
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (this.config.hideOngoing) {
|
||||
if (event.startDate < now) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (this.listContainsEvent(events, event)) {
|
||||
continue;
|
||||
}
|
||||
event.url = calendarUrl;
|
||||
event.today = event.startDate >= today && event.startDate < today + 24 * 60 * 60 * 1000;
|
||||
|
||||
/* if sliceMultiDayEvents is set to true, multiday events (events exceeding at least one midnight) are sliced into days,
|
||||
* otherwise, esp. in dateheaders mode it is not clear how long these events are.
|
||||
*/
|
||||
const maxCount = Math.ceil((event.endDate - 1 - moment(event.startDate, "x").endOf("day").format("x")) / (1000 * 60 * 60 * 24)) + 1;
|
||||
if (this.config.sliceMultiDayEvents && maxCount > 1) {
|
||||
const splitEvents = [];
|
||||
let midnight = moment(event.startDate, "x").clone().startOf("day").add(1, "day").format("x");
|
||||
let count = 1;
|
||||
while (event.endDate > midnight) {
|
||||
const thisEvent = JSON.parse(JSON.stringify(event)); // clone object
|
||||
thisEvent.today = thisEvent.startDate >= today && thisEvent.startDate < today + 24 * 60 * 60 * 1000;
|
||||
thisEvent.endDate = midnight;
|
||||
thisEvent.title += " (" + count + "/" + maxCount + ")";
|
||||
splitEvents.push(thisEvent);
|
||||
|
||||
event.startDate = midnight;
|
||||
count += 1;
|
||||
midnight = moment(midnight, "x").add(1, "day").format("x"); // next day
|
||||
}
|
||||
// Last day
|
||||
event.title += " (" + count + "/" + maxCount + ")";
|
||||
splitEvents.push(event);
|
||||
|
||||
for (let splitEvent of splitEvents) {
|
||||
if (splitEvent.endDate > now && splitEvent.endDate <= future) {
|
||||
events.push(splitEvent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
events.push(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
events.sort(function (a, b) {
|
||||
return a.startDate - b.startDate;
|
||||
});
|
||||
|
||||
// Limit the number of days displayed
|
||||
// If limitDays is set > 0, limit display to that number of days
|
||||
if (this.config.limitDays > 0) {
|
||||
let newEvents = [];
|
||||
let lastDate = today.clone().subtract(1, "days").format("YYYYMMDD");
|
||||
let days = 0;
|
||||
for (const ev of events) {
|
||||
let eventDate = moment(ev.startDate, "x").format("YYYYMMDD");
|
||||
// if date of event is later than lastdate
|
||||
// check if we already are showing max unique days
|
||||
if (eventDate > lastDate) {
|
||||
// if the only entry in the first day is a full day event that day is not counted as unique
|
||||
if (newEvents.length === 1 && days === 1 && newEvents[0].fullDayEvent) {
|
||||
days--;
|
||||
}
|
||||
days++;
|
||||
if (days > this.config.limitDays) {
|
||||
continue;
|
||||
} else {
|
||||
lastDate = eventDate;
|
||||
}
|
||||
}
|
||||
newEvents.push(ev);
|
||||
}
|
||||
events = newEvents;
|
||||
}
|
||||
|
||||
return events.slice(0, this.config.maximumEntries);
|
||||
},
|
||||
|
||||
listContainsEvent: function (eventList, event) {
|
||||
for (const evt of eventList) {
|
||||
if (evt.title === event.title && parseInt(evt.startDate) === parseInt(event.startDate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Requests node helper to add calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url to add
|
||||
* @param {object} auth The authentication method and credentials
|
||||
* @param {object} calendarConfig The config of the specific calendar
|
||||
*/
|
||||
addCalendar: function (url, auth, calendarConfig) {
|
||||
this.sendSocketNotification("ADD_CALENDAR", {
|
||||
id: this.identifier,
|
||||
url: url,
|
||||
excludedEvents: calendarConfig.excludedEvents || this.config.excludedEvents,
|
||||
maximumEntries: calendarConfig.maximumEntries || this.config.maximumEntries,
|
||||
maximumNumberOfDays: calendarConfig.maximumNumberOfDays || this.config.maximumNumberOfDays,
|
||||
fetchInterval: this.config.fetchInterval,
|
||||
symbolClass: calendarConfig.symbolClass,
|
||||
titleClass: calendarConfig.titleClass,
|
||||
timeClass: calendarConfig.timeClass,
|
||||
auth: auth,
|
||||
broadcastPastEvents: calendarConfig.broadcastPastEvents || this.config.broadcastPastEvents,
|
||||
selfSignedCert: calendarConfig.selfSignedCert || this.config.selfSignedCert
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the symbols for a specific event.
|
||||
*
|
||||
* @param {object} event Event to look for.
|
||||
* @returns {string[]} The symbols
|
||||
*/
|
||||
symbolsForEvent: function (event) {
|
||||
let symbols = this.getCalendarPropertyAsArray(event.url, "symbol", this.config.defaultSymbol);
|
||||
|
||||
if (event.recurringEvent === true && this.hasCalendarProperty(event.url, "recurringSymbol")) {
|
||||
symbols = this.mergeUnique(this.getCalendarPropertyAsArray(event.url, "recurringSymbol", this.config.defaultSymbol), symbols);
|
||||
}
|
||||
|
||||
if (event.fullDayEvent === true && this.hasCalendarProperty(event.url, "fullDaySymbol")) {
|
||||
symbols = this.mergeUnique(this.getCalendarPropertyAsArray(event.url, "fullDaySymbol", this.config.defaultSymbol), symbols);
|
||||
}
|
||||
|
||||
return symbols;
|
||||
},
|
||||
|
||||
mergeUnique: function (arr1, arr2) {
|
||||
return arr1.concat(
|
||||
arr2.filter(function (item) {
|
||||
return arr1.indexOf(item) === -1;
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the symbolClass for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The class to be used for the symbols of the calendar
|
||||
*/
|
||||
symbolClassForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "symbolClass", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the titleClass for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The class to be used for the title of the calendar
|
||||
*/
|
||||
titleClassForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "titleClass", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the timeClass for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The class to be used for the time of the calendar
|
||||
*/
|
||||
timeClassForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "timeClass", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the calendar name for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The name of the calendar
|
||||
*/
|
||||
calendarNameForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "name", "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the color for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The color
|
||||
*/
|
||||
colorForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "color", "#fff");
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the count title for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @returns {string} The title
|
||||
*/
|
||||
countTitleForUrl: function (url) {
|
||||
return this.getCalendarProperty(url, "repeatingCountTitle", this.config.defaultRepeatingCountTitle);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper method to retrieve the property for a specific calendar url.
|
||||
*
|
||||
* @param {string} url The calendar url
|
||||
* @param {string} property The property to look for
|
||||
* @param {string} defaultValue The value if the property is not found
|
||||
* @returns {*} The property
|
||||
*/
|
||||
getCalendarProperty: function (url, property, defaultValue) {
|
||||
for (const calendar of this.config.calendars) {
|
||||
if (calendar.url === url && calendar.hasOwnProperty(property)) {
|
||||
return calendar[property];
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
getCalendarPropertyAsArray: function (url, property, defaultValue) {
|
||||
let p = this.getCalendarProperty(url, property, defaultValue);
|
||||
if (!(p instanceof Array)) p = [p];
|
||||
return p;
|
||||
},
|
||||
|
||||
hasCalendarProperty: function (url, property) {
|
||||
return !!this.getCalendarProperty(url, property, undefined);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shortens a string if it's longer than maxLength and add a ellipsis to the end
|
||||
*
|
||||
* @param {string} string Text string to shorten
|
||||
* @param {number} maxLength The max length of the string
|
||||
* @param {boolean} wrapEvents Wrap the text after the line has reached maxLength
|
||||
* @param {number} maxTitleLines The max number of vertical lines before cutting event title
|
||||
* @returns {string} The shortened string
|
||||
*/
|
||||
shorten: function (string, maxLength, wrapEvents, maxTitleLines) {
|
||||
if (typeof string !== "string") {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (wrapEvents === true) {
|
||||
const words = string.split(" ");
|
||||
let temp = "";
|
||||
let currentLine = "";
|
||||
let line = 0;
|
||||
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
const word = words[i];
|
||||
if (currentLine.length + word.length < (typeof maxLength === "number" ? maxLength : 25) - 1) {
|
||||
// max - 1 to account for a space
|
||||
currentLine += word + " ";
|
||||
} else {
|
||||
line++;
|
||||
if (line > maxTitleLines - 1) {
|
||||
if (i < words.length) {
|
||||
currentLine += "…";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentLine.length > 0) {
|
||||
temp += currentLine + "<br>" + word + " ";
|
||||
} else {
|
||||
temp += word + "<br>";
|
||||
}
|
||||
currentLine = "";
|
||||
}
|
||||
}
|
||||
|
||||
return (temp + currentLine).trim();
|
||||
} else {
|
||||
if (maxLength && typeof maxLength === "number" && string.length > maxLength) {
|
||||
return string.trim().slice(0, maxLength) + "…";
|
||||
} else {
|
||||
return string.trim();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Capitalize the first letter of a string
|
||||
*
|
||||
* @param {string} string The string to capitalize
|
||||
* @returns {string} The capitalized string
|
||||
*/
|
||||
capFirst: function (string) {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Transforms the title of an event for usage.
|
||||
* Replaces parts of the text as defined in config.titleReplace.
|
||||
* Shortens title based on config.maxTitleLength and config.wrapEvents
|
||||
*
|
||||
* @param {string} title The title to transform.
|
||||
* @param {object} titleReplace Pairs of strings to be replaced in the title
|
||||
* @param {boolean} wrapEvents Wrap the text after the line has reached maxLength
|
||||
* @param {number} maxTitleLength The max length of the string
|
||||
* @param {number} maxTitleLines The max number of vertical lines before cutting event title
|
||||
* @returns {string} The transformed title.
|
||||
*/
|
||||
titleTransform: function (title, titleReplace, wrapEvents, maxTitleLength, maxTitleLines) {
|
||||
for (let needle in titleReplace) {
|
||||
const replacement = titleReplace[needle];
|
||||
|
||||
const regParts = needle.match(/^\/(.+)\/([gim]*)$/);
|
||||
if (regParts) {
|
||||
// the parsed pattern is a regexp.
|
||||
needle = new RegExp(regParts[1], regParts[2]);
|
||||
}
|
||||
|
||||
title = title.replace(needle, replacement);
|
||||
}
|
||||
|
||||
title = this.shorten(title, maxTitleLength, wrapEvents, maxTitleLines);
|
||||
return title;
|
||||
},
|
||||
|
||||
/**
|
||||
* Broadcasts the events to all other modules for reuse.
|
||||
* The all events available in one array, sorted on startdate.
|
||||
*/
|
||||
broadcastEvents: function () {
|
||||
const eventList = [];
|
||||
for (const url in this.calendarData) {
|
||||
for (const ev of this.calendarData[url]) {
|
||||
const event = cloneObject(ev);
|
||||
event.symbol = this.symbolsForEvent(event);
|
||||
event.calendarName = this.calendarNameForUrl(url);
|
||||
event.color = this.colorForUrl(url);
|
||||
delete event.url;
|
||||
eventList.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
eventList.sort(function (a, b) {
|
||||
return a.startDate - b.startDate;
|
||||
});
|
||||
|
||||
this.sendNotification("CALENDAR_EVENTS", eventList);
|
||||
}
|
||||
});
|
||||
158
modules/default/calendar/calendarfetcher.js
Normal file
158
modules/default/calendar/calendarfetcher.js
Normal file
@@ -0,0 +1,158 @@
|
||||
/* Magic Mirror
|
||||
* Node Helper: Calendar - CalendarFetcher
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
const CalendarUtils = require("./calendarutils");
|
||||
const Log = require("logger");
|
||||
const NodeHelper = require("node_helper");
|
||||
const ical = require("node-ical");
|
||||
const fetch = require("node-fetch");
|
||||
const digest = require("digest-fetch");
|
||||
const https = require("https");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} url The url of the calendar to fetch
|
||||
* @param {number} reloadInterval Time in ms the calendar is fetched again
|
||||
* @param {string[]} excludedEvents An array of words / phrases from event titles that will be excluded from being shown.
|
||||
* @param {number} maximumEntries The maximum number of events fetched.
|
||||
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
|
||||
* @param {object} auth The object containing options for authentication against the calendar.
|
||||
* @param {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too
|
||||
* @param {boolean} selfSignedCert If true, the server certificate is not verified against the list of supplied CAs.
|
||||
* @class
|
||||
*/
|
||||
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents, selfSignedCert) {
|
||||
let reloadTimer = null;
|
||||
let events = [];
|
||||
|
||||
let fetchFailedCallback = function () {};
|
||||
let eventsReceivedCallback = function () {};
|
||||
|
||||
/**
|
||||
* Initiates calendar fetch.
|
||||
*/
|
||||
const fetchCalendar = () => {
|
||||
clearTimeout(reloadTimer);
|
||||
reloadTimer = null;
|
||||
const nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]);
|
||||
let fetcher = null;
|
||||
let httpsAgent = null;
|
||||
let headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Node.js " + nodeVersion + ") MagicMirror/" + global.version + " (https://github.com/MichMich/MagicMirror/)"
|
||||
};
|
||||
|
||||
if (selfSignedCert) {
|
||||
httpsAgent = new https.Agent({
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
}
|
||||
if (auth) {
|
||||
if (auth.method === "bearer") {
|
||||
headers.Authorization = "Bearer " + auth.pass;
|
||||
} else if (auth.method === "digest") {
|
||||
fetcher = new digest(auth.user, auth.pass).fetch(url, { headers: headers, agent: httpsAgent });
|
||||
} else {
|
||||
headers.Authorization = "Basic " + Buffer.from(auth.user + ":" + auth.pass).toString("base64");
|
||||
}
|
||||
}
|
||||
if (fetcher === null) {
|
||||
fetcher = fetch(url, { headers: headers, agent: httpsAgent });
|
||||
}
|
||||
|
||||
fetcher
|
||||
.then(NodeHelper.checkFetchStatus)
|
||||
.then((response) => response.text())
|
||||
.then((responseData) => {
|
||||
let data = [];
|
||||
|
||||
try {
|
||||
data = ical.parseICS(responseData);
|
||||
Log.debug("parsed data=" + JSON.stringify(data));
|
||||
events = CalendarUtils.filterEvents(data, {
|
||||
excludedEvents,
|
||||
includePastEvents,
|
||||
maximumEntries,
|
||||
maximumNumberOfDays
|
||||
});
|
||||
} catch (error) {
|
||||
fetchFailedCallback(this, error);
|
||||
scheduleTimer();
|
||||
return;
|
||||
}
|
||||
this.broadcastEvents();
|
||||
scheduleTimer();
|
||||
})
|
||||
.catch((error) => {
|
||||
fetchFailedCallback(this, error);
|
||||
scheduleTimer();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Schedule the timer for the next update.
|
||||
*/
|
||||
const scheduleTimer = function () {
|
||||
clearTimeout(reloadTimer);
|
||||
reloadTimer = setTimeout(function () {
|
||||
fetchCalendar();
|
||||
}, reloadInterval);
|
||||
};
|
||||
|
||||
/* public methods */
|
||||
|
||||
/**
|
||||
* Initiate fetchCalendar();
|
||||
*/
|
||||
this.startFetch = function () {
|
||||
fetchCalendar();
|
||||
};
|
||||
|
||||
/**
|
||||
* Broadcast the existing events.
|
||||
*/
|
||||
this.broadcastEvents = function () {
|
||||
Log.info("Calendar-Fetcher: Broadcasting " + events.length + " events.");
|
||||
eventsReceivedCallback(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the on success callback
|
||||
*
|
||||
* @param {Function} callback The on success callback.
|
||||
*/
|
||||
this.onReceive = function (callback) {
|
||||
eventsReceivedCallback = callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the on error callback
|
||||
*
|
||||
* @param {Function} callback The on error callback.
|
||||
*/
|
||||
this.onError = function (callback) {
|
||||
fetchFailedCallback = callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the url of this fetcher.
|
||||
*
|
||||
* @returns {string} The url of this fetcher.
|
||||
*/
|
||||
this.url = function () {
|
||||
return url;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns current available events for this fetcher.
|
||||
*
|
||||
* @returns {object[]} The current available events for this fetcher.
|
||||
*/
|
||||
this.events = function () {
|
||||
return events;
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = CalendarFetcher;
|
||||
623
modules/default/calendar/calendarutils.js
Normal file
623
modules/default/calendar/calendarutils.js
Normal file
@@ -0,0 +1,623 @@
|
||||
/* Magic Mirror
|
||||
* Calendar Util Methods
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external Moment
|
||||
*/
|
||||
const moment = require("moment");
|
||||
const path = require("path");
|
||||
const zoneTable = require(path.join(__dirname, "windowsZones.json"));
|
||||
const Log = require("../../../js/logger.js");
|
||||
|
||||
const CalendarUtils = {
|
||||
/**
|
||||
* Calculate the time correction, either dst/std or full day in cases where
|
||||
* utc time is day before plus offset
|
||||
*
|
||||
* @param {object} event the event which needs adjustement
|
||||
* @param {Date} date the date on which this event happens
|
||||
* @returns {number} the necessary adjustment in hours
|
||||
*/
|
||||
calculateTimezoneAdjustment: function (event, date) {
|
||||
let adjustHours = 0;
|
||||
// if a timezone was specified
|
||||
if (!event.start.tz) {
|
||||
Log.debug(" if no tz, guess based on now");
|
||||
event.start.tz = moment.tz.guess();
|
||||
}
|
||||
Log.debug("initial tz=" + event.start.tz);
|
||||
|
||||
// if there is a start date specified
|
||||
if (event.start.tz) {
|
||||
// if this is a windows timezone
|
||||
if (event.start.tz.includes(" ")) {
|
||||
// use the lookup table to get theIANA name as moment and date don't know MS timezones
|
||||
let tz = CalendarUtils.getIanaTZFromMS(event.start.tz);
|
||||
Log.debug("corrected TZ=" + tz);
|
||||
// watch out for unregistered windows timezone names
|
||||
// if we had a successful lookup
|
||||
if (tz) {
|
||||
// change the timezone to the IANA name
|
||||
event.start.tz = tz;
|
||||
// Log.debug("corrected timezone="+event.start.tz)
|
||||
}
|
||||
}
|
||||
Log.debug("corrected tz=" + event.start.tz);
|
||||
let current_offset = 0; // offset from TZ string or calculated
|
||||
let mm = 0; // date with tz or offset
|
||||
let start_offset = 0; // utc offset of created with tz
|
||||
// if there is still an offset, lookup failed, use it
|
||||
if (event.start.tz.startsWith("(")) {
|
||||
const regex = /[+|-]\d*:\d*/;
|
||||
const start_offsetString = event.start.tz.match(regex).toString().split(":");
|
||||
let start_offset = parseInt(start_offsetString[0]);
|
||||
start_offset *= event.start.tz[1] === "-" ? -1 : 1;
|
||||
adjustHours = start_offset;
|
||||
Log.debug("defined offset=" + start_offset + " hours");
|
||||
current_offset = start_offset;
|
||||
event.start.tz = "";
|
||||
Log.debug("ical offset=" + current_offset + " date=" + date);
|
||||
mm = moment(date);
|
||||
let x = parseInt(moment(new Date()).utcOffset());
|
||||
Log.debug("net mins=" + (current_offset * 60 - x));
|
||||
|
||||
mm = mm.add(x - current_offset * 60, "minutes");
|
||||
adjustHours = (current_offset * 60 - x) / 60;
|
||||
event.start = mm.toDate();
|
||||
Log.debug("adjusted date=" + event.start);
|
||||
} else {
|
||||
// get the start time in that timezone
|
||||
let es = moment(event.start);
|
||||
// check for start date prior to start of daylight changing date
|
||||
if (es.format("YYYY") < 2007) {
|
||||
es.set("year", 2013); // if so, use a closer date
|
||||
}
|
||||
Log.debug("start date/time=" + es.toDate());
|
||||
start_offset = moment.tz(es, event.start.tz).utcOffset();
|
||||
Log.debug("start offset=" + start_offset);
|
||||
|
||||
Log.debug("start date/time w tz =" + moment.tz(moment(event.start), event.start.tz).toDate());
|
||||
|
||||
// get the specified date in that timezone
|
||||
mm = moment.tz(moment(date), event.start.tz);
|
||||
Log.debug("event date=" + mm.toDate());
|
||||
current_offset = mm.utcOffset();
|
||||
}
|
||||
Log.debug("event offset=" + current_offset + " hour=" + mm.format("H") + " event date=" + mm.toDate());
|
||||
|
||||
// if the offset is greater than 0, east of london
|
||||
if (current_offset !== start_offset) {
|
||||
// big offset
|
||||
Log.debug("offset");
|
||||
let h = parseInt(mm.format("H"));
|
||||
// check if the event time is less than the offset
|
||||
if (h > 0 && h < Math.abs(current_offset) / 60) {
|
||||
// if so, rrule created a wrong date (utc day, oops, with utc yesterday adjusted time)
|
||||
// we need to fix that
|
||||
adjustHours = 24;
|
||||
// Log.debug("adjusting date")
|
||||
}
|
||||
//-300 > -240
|
||||
//if (Math.abs(current_offset) > Math.abs(start_offset)){
|
||||
if (current_offset > start_offset) {
|
||||
adjustHours -= 1;
|
||||
Log.debug("adjust down 1 hour dst change");
|
||||
//} else if (Math.abs(current_offset) < Math.abs(start_offset)) {
|
||||
} else if (current_offset < start_offset) {
|
||||
adjustHours += 1;
|
||||
Log.debug("adjust up 1 hour dst change");
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.debug("adjustHours=" + adjustHours);
|
||||
return adjustHours;
|
||||
},
|
||||
|
||||
/**
|
||||
* Filter the events from ical according to the given config
|
||||
*
|
||||
* @param {object} data the calendar data from ical
|
||||
* @param {object} config The configuration object
|
||||
* @returns {string[]} the filtered events
|
||||
*/
|
||||
filterEvents: function (data, config) {
|
||||
const newEvents = [];
|
||||
|
||||
// limitFunction doesn't do much limiting, see comment re: the dates
|
||||
// array in rrule section below as to why we need to do the filtering
|
||||
// ourselves
|
||||
const limitFunction = function (date, i) {
|
||||
return true;
|
||||
};
|
||||
|
||||
const eventDate = function (event, time) {
|
||||
return CalendarUtils.isFullDayEvent(event) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
||||
};
|
||||
|
||||
Log.debug("There are " + Object.entries(data).length + " calendar entries.");
|
||||
Object.entries(data).forEach(([key, event]) => {
|
||||
Log.debug("Processing entry...");
|
||||
const now = new Date();
|
||||
const today = moment().startOf("day").toDate();
|
||||
const future = moment().startOf("day").add(config.maximumNumberOfDays, "days").subtract(1, "seconds").toDate(); // Subtract 1 second so that events that start on the middle of the night will not repeat.
|
||||
let past = today;
|
||||
|
||||
if (config.includePastEvents) {
|
||||
past = moment().startOf("day").subtract(config.maximumNumberOfDays, "days").toDate();
|
||||
}
|
||||
|
||||
// FIXME: Ugly fix to solve the facebook birthday issue.
|
||||
// Otherwise, the recurring events only show the birthday for next year.
|
||||
let isFacebookBirthday = false;
|
||||
if (typeof event.uid !== "undefined") {
|
||||
if (event.uid.indexOf("@facebook.com") !== -1) {
|
||||
isFacebookBirthday = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === "VEVENT") {
|
||||
Log.debug("\nEvent: " + JSON.stringify(event));
|
||||
let startDate = eventDate(event, "start");
|
||||
let endDate;
|
||||
|
||||
if (typeof event.end !== "undefined") {
|
||||
endDate = eventDate(event, "end");
|
||||
} else if (typeof event.duration !== "undefined") {
|
||||
endDate = startDate.clone().add(moment.duration(event.duration));
|
||||
} else {
|
||||
if (!isFacebookBirthday) {
|
||||
// make copy of start date, separate storage area
|
||||
endDate = moment(startDate.format("x"), "x");
|
||||
} else {
|
||||
endDate = moment(startDate).add(1, "days");
|
||||
}
|
||||
}
|
||||
|
||||
Log.debug("startDate (local): " + startDate.toDate());
|
||||
Log.debug("endDate (local): " + endDate.toDate());
|
||||
|
||||
// Calculate the duration of the event for use with recurring events.
|
||||
let duration = parseInt(endDate.format("x")) - parseInt(startDate.format("x"));
|
||||
Log.debug("duration: " + duration);
|
||||
|
||||
// FIXME: Since the parsed json object from node-ical comes with time information
|
||||
// this check could be removed (?)
|
||||
if (event.start.length === 8) {
|
||||
startDate = startDate.startOf("day");
|
||||
}
|
||||
|
||||
const title = CalendarUtils.getTitleFromEvent(event);
|
||||
Log.debug("title: " + title);
|
||||
|
||||
let excluded = false,
|
||||
dateFilter = null;
|
||||
|
||||
for (let f in config.excludedEvents) {
|
||||
let filter = config.excludedEvents[f],
|
||||
testTitle = title.toLowerCase(),
|
||||
until = null,
|
||||
useRegex = false,
|
||||
regexFlags = "g";
|
||||
|
||||
if (filter instanceof Object) {
|
||||
if (typeof filter.until !== "undefined") {
|
||||
until = filter.until;
|
||||
}
|
||||
|
||||
if (typeof filter.regex !== "undefined") {
|
||||
useRegex = filter.regex;
|
||||
}
|
||||
|
||||
// If additional advanced filtering is added in, this section
|
||||
// must remain last as we overwrite the filter object with the
|
||||
// filterBy string
|
||||
if (filter.caseSensitive) {
|
||||
filter = filter.filterBy;
|
||||
testTitle = title;
|
||||
} else if (useRegex) {
|
||||
filter = filter.filterBy;
|
||||
testTitle = title;
|
||||
regexFlags += "i";
|
||||
} else {
|
||||
filter = filter.filterBy.toLowerCase();
|
||||
}
|
||||
} else {
|
||||
filter = filter.toLowerCase();
|
||||
}
|
||||
|
||||
if (CalendarUtils.titleFilterApplies(testTitle, filter, useRegex, regexFlags)) {
|
||||
if (until) {
|
||||
dateFilter = until;
|
||||
} else {
|
||||
excluded = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (excluded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const location = event.location || false;
|
||||
const geo = event.geo || false;
|
||||
const description = event.description || false;
|
||||
|
||||
if (typeof event.rrule !== "undefined" && event.rrule !== null && !isFacebookBirthday) {
|
||||
const rule = event.rrule;
|
||||
let addedEvents = 0;
|
||||
|
||||
const pastMoment = moment(past);
|
||||
const futureMoment = moment(future);
|
||||
|
||||
// can cause problems with e.g. birthdays before 1900
|
||||
if ((rule.options && rule.origOptions && rule.origOptions.dtstart && rule.origOptions.dtstart.getFullYear() < 1900) || (rule.options && rule.options.dtstart && rule.options.dtstart.getFullYear() < 1900)) {
|
||||
rule.origOptions.dtstart.setYear(1900);
|
||||
rule.options.dtstart.setYear(1900);
|
||||
}
|
||||
|
||||
// For recurring events, get the set of start dates that fall within the range
|
||||
// of dates we're looking for.
|
||||
// kblankenship1989 - to fix issue #1798, converting all dates to locale time first, then converting back to UTC time
|
||||
let pastLocal = 0;
|
||||
let futureLocal = 0;
|
||||
if (CalendarUtils.isFullDayEvent(event)) {
|
||||
Log.debug("fullday");
|
||||
// if full day event, only use the date part of the ranges
|
||||
pastLocal = pastMoment.toDate();
|
||||
futureLocal = futureMoment.toDate();
|
||||
|
||||
Log.debug("pastLocal: " + pastLocal);
|
||||
Log.debug("futureLocal: " + futureLocal);
|
||||
} else {
|
||||
// if we want past events
|
||||
if (config.includePastEvents) {
|
||||
// use the calculated past time for the between from
|
||||
pastLocal = pastMoment.toDate();
|
||||
} else {
|
||||
// otherwise use NOW.. cause we shouldn't use any before now
|
||||
pastLocal = moment().toDate(); //now
|
||||
}
|
||||
futureLocal = futureMoment.toDate(); // future
|
||||
}
|
||||
Log.debug("Search for recurring events between: " + pastLocal + " and " + futureLocal);
|
||||
const dates = rule.between(pastLocal, futureLocal, true, limitFunction);
|
||||
Log.debug("Title: " + event.summary + ", with dates: " + JSON.stringify(dates));
|
||||
// The "dates" array contains the set of dates within our desired date range range that are valid
|
||||
// for the recurrence rule. *However*, it's possible for us to have a specific recurrence that
|
||||
// had its date changed from outside the range to inside the range. For the time being,
|
||||
// we'll handle this by adding *all* recurrence entries into the set of dates that we check,
|
||||
// because the logic below will filter out any recurrences that don't actually belong within
|
||||
// our display range.
|
||||
// Would be great if there was a better way to handle this.
|
||||
Log.debug("event.recurrences: " + event.recurrences);
|
||||
if (event.recurrences !== undefined) {
|
||||
for (let r in event.recurrences) {
|
||||
// Only add dates that weren't already in the range we added from the rrule so that
|
||||
// we don"t double-add those events.
|
||||
if (moment(new Date(r)).isBetween(pastMoment, futureMoment) !== true) {
|
||||
dates.push(new Date(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Loop through the set of date entries to see which recurrences should be added to our event list.
|
||||
for (let d in dates) {
|
||||
let date = dates[d];
|
||||
// Remove the time information of each date by using its substring, using the following method:
|
||||
// .toISOString().substring(0,10).
|
||||
// since the date is given as ISOString with YYYY-MM-DDTHH:MM:SS.SSSZ
|
||||
// (see https://momentjs.com/docs/#/displaying/as-iso-string/).
|
||||
const dateKey = date.toISOString().substring(0, 10);
|
||||
let curEvent = event;
|
||||
let showRecurrence = true;
|
||||
|
||||
// Get the offset of today where we are processing
|
||||
// This will be the correction, we need to apply.
|
||||
let nowOffset = new Date().getTimezoneOffset();
|
||||
// For full day events, the time might be off from RRULE/Luxon problem
|
||||
// Get time zone offset of the rule calculated event
|
||||
let dateoffset = date.getTimezoneOffset();
|
||||
|
||||
// Reduce the time by the following offset.
|
||||
Log.debug(" recurring date is " + date + " offset is " + dateoffset);
|
||||
|
||||
let dh = moment(date).format("HH");
|
||||
Log.debug(" recurring date is " + date + " offset is " + dateoffset / 60 + " Hour is " + dh);
|
||||
|
||||
if (CalendarUtils.isFullDayEvent(event)) {
|
||||
Log.debug("Fullday");
|
||||
// If the offset is negative (east of GMT), where the problem is
|
||||
if (dateoffset < 0) {
|
||||
// Remove the offset, independently of the comparison between the date hour and the offset,
|
||||
// since in the case that *date houre < offset*, the *new Date* command will handle this by
|
||||
// representing the day before.
|
||||
|
||||
// Reduce the time by the offset:
|
||||
// Apply the correction to the date/time to get it UTC relative
|
||||
date = new Date(date.getTime() - Math.abs(nowOffset) * 60000);
|
||||
// the duration was calculated way back at the top before we could correct the start time..
|
||||
// fix it for this event entry
|
||||
//duration = 24 * 60 * 60 * 1000;
|
||||
Log.debug("new recurring date1 is " + date);
|
||||
} else {
|
||||
// if the timezones are the same, correct date if needed
|
||||
if (event.start.tz === moment.tz.guess()) {
|
||||
// if the date hour is less than the offset
|
||||
if (24 - dh < Math.abs(dateoffset / 60)) {
|
||||
// apply the correction to the date/time back to right day
|
||||
date = new Date(date.getTime() + Math.abs(24 * 60) * 60000);
|
||||
// the duration was calculated way back at the top before we could correct the start time..
|
||||
// fix it for this event entry
|
||||
//duration = 24 * 60 * 60 * 1000;
|
||||
Log.debug("new recurring date2 is " + date);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// not full day, but luxon can still screw up the date on the rule processing
|
||||
// we need to correct the date to get back to the right event for
|
||||
if (dateoffset < 0) {
|
||||
// if the date hour is less than the offset
|
||||
if (dh < Math.abs(dateoffset / 60)) {
|
||||
// Reduce the time by the offset:
|
||||
// Apply the correction to the date/time to get it UTC relative
|
||||
date = new Date(date.getTime() - Math.abs(nowOffset) * 60000);
|
||||
// the duration was calculated way back at the top before we could correct the start time..
|
||||
// fix it for this event entry
|
||||
//duration = 24 * 60 * 60 * 1000;
|
||||
Log.debug("new recurring date1 is " + date);
|
||||
}
|
||||
} else {
|
||||
// if the timezones are the same, correct date if needed
|
||||
if (event.start.tz === moment.tz.guess()) {
|
||||
// if the date hour is less than the offset
|
||||
if (24 - dh < Math.abs(dateoffset / 60)) {
|
||||
// apply the correction to the date/time back to right day
|
||||
date = new Date(date.getTime() + Math.abs(24 * 60) * 60000);
|
||||
// the duration was calculated way back at the top before we could correct the start time..
|
||||
// fix it for this event entry
|
||||
//duration = 24 * 60 * 60 * 1000;
|
||||
Log.debug("new recurring date2 is " + date);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
startDate = moment(date);
|
||||
Log.debug("Corrected startDate (local): " + startDate.toDate());
|
||||
|
||||
let adjustDays = CalendarUtils.calculateTimezoneAdjustment(event, date);
|
||||
|
||||
// For each date that we're checking, it's possible that there is a recurrence override for that one day.
|
||||
if (curEvent.recurrences !== undefined && curEvent.recurrences[dateKey] !== undefined) {
|
||||
// We found an override, so for this recurrence, use a potentially different title, start date, and duration.
|
||||
curEvent = curEvent.recurrences[dateKey];
|
||||
startDate = moment(curEvent.start);
|
||||
duration = parseInt(moment(curEvent.end).format("x")) - parseInt(startDate.format("x"));
|
||||
}
|
||||
// If there's no recurrence override, check for an exception date. Exception dates represent exceptions to the rule.
|
||||
else if (curEvent.exdate !== undefined && curEvent.exdate[dateKey] !== undefined) {
|
||||
// This date is an exception date, which means we should skip it in the recurrence pattern.
|
||||
showRecurrence = false;
|
||||
}
|
||||
Log.debug("duration: " + duration);
|
||||
|
||||
endDate = moment(parseInt(startDate.format("x")) + duration, "x");
|
||||
if (startDate.format("x") === endDate.format("x")) {
|
||||
endDate = endDate.endOf("day");
|
||||
}
|
||||
|
||||
const recurrenceTitle = CalendarUtils.getTitleFromEvent(curEvent);
|
||||
|
||||
// If this recurrence ends before the start of the date range, or starts after the end of the date range, don"t add
|
||||
// it to the event list.
|
||||
if (endDate.isBefore(past) || startDate.isAfter(future)) {
|
||||
showRecurrence = false;
|
||||
}
|
||||
|
||||
if (CalendarUtils.timeFilterApplies(now, endDate, dateFilter)) {
|
||||
showRecurrence = false;
|
||||
}
|
||||
|
||||
if (showRecurrence === true) {
|
||||
Log.debug("saving event: " + description);
|
||||
addedEvents++;
|
||||
newEvents.push({
|
||||
title: recurrenceTitle,
|
||||
startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"),
|
||||
endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"),
|
||||
fullDayEvent: CalendarUtils.isFullDayEvent(event),
|
||||
recurringEvent: true,
|
||||
class: event.class,
|
||||
firstYear: event.start.getFullYear(),
|
||||
location: location,
|
||||
geo: geo,
|
||||
description: description
|
||||
});
|
||||
}
|
||||
}
|
||||
// End recurring event parsing.
|
||||
} else {
|
||||
// Single event.
|
||||
const fullDayEvent = isFacebookBirthday ? true : CalendarUtils.isFullDayEvent(event);
|
||||
// Log.debug("full day event")
|
||||
|
||||
if (config.includePastEvents) {
|
||||
// Past event is too far in the past, so skip.
|
||||
if (endDate < past) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// It's not a fullday event, and it is in the past, so skip.
|
||||
if (!fullDayEvent && endDate < new Date()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// It's a fullday event, and it is before today, So skip.
|
||||
if (fullDayEvent && endDate <= today) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// It exceeds the maximumNumberOfDays limit, so skip.
|
||||
if (startDate > future) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CalendarUtils.timeFilterApplies(now, endDate, dateFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust start date so multiple day events will be displayed as happening today even though they started some days ago already
|
||||
if (fullDayEvent && startDate <= today) {
|
||||
startDate = moment(today);
|
||||
}
|
||||
// if the start and end are the same, then make end the 'end of day' value (start is at 00:00:00)
|
||||
if (fullDayEvent && startDate.format("x") === endDate.format("x")) {
|
||||
endDate = endDate.endOf("day");
|
||||
}
|
||||
// get correction for date saving and dst change between now and then
|
||||
let adjustDays = CalendarUtils.calculateTimezoneAdjustment(event, startDate.toDate());
|
||||
// Every thing is good. Add it to the list.
|
||||
newEvents.push({
|
||||
title: title,
|
||||
startDate: (adjustDays ? (adjustDays > 0 ? startDate.add(adjustDays, "hours") : startDate.subtract(Math.abs(adjustDays), "hours")) : startDate).format("x"),
|
||||
endDate: (adjustDays ? (adjustDays > 0 ? endDate.add(adjustDays, "hours") : endDate.subtract(Math.abs(adjustDays), "hours")) : endDate).format("x"),
|
||||
fullDayEvent: fullDayEvent,
|
||||
class: event.class,
|
||||
location: location,
|
||||
geo: geo,
|
||||
description: description
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
newEvents.sort(function (a, b) {
|
||||
return a.startDate - b.startDate;
|
||||
});
|
||||
|
||||
// include up to maximumEntries current or upcoming events
|
||||
// If past events should be included, include all past events
|
||||
const now = moment();
|
||||
let entries = 0;
|
||||
let events = [];
|
||||
for (let ne of newEvents) {
|
||||
if (moment(ne.endDate, "x").isBefore(now)) {
|
||||
if (config.includePastEvents) events.push(ne);
|
||||
continue;
|
||||
}
|
||||
entries++;
|
||||
// If max events has been saved, skip the rest
|
||||
if (entries > config.maximumEntries) break;
|
||||
events.push(ne);
|
||||
}
|
||||
|
||||
return events;
|
||||
},
|
||||
|
||||
/**
|
||||
* Lookup iana tz from windows
|
||||
*
|
||||
* @param {string} msTZName the timezone name to lookup
|
||||
* @returns {string|null} the iana name or null of none is found
|
||||
*/
|
||||
getIanaTZFromMS: function (msTZName) {
|
||||
// Get hash entry
|
||||
const he = zoneTable[msTZName];
|
||||
// If found return iana name, else null
|
||||
return he ? he.iana[0] : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the title from the event.
|
||||
*
|
||||
* @param {object} event The event object to check.
|
||||
* @returns {string} The title of the event, or "Event" if no title is found.
|
||||
*/
|
||||
getTitleFromEvent: function (event) {
|
||||
let title = "Event";
|
||||
if (event.summary) {
|
||||
title = typeof event.summary.val !== "undefined" ? event.summary.val : event.summary;
|
||||
} else if (event.description) {
|
||||
title = event.description;
|
||||
}
|
||||
|
||||
return title;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if an event is a fullday event.
|
||||
*
|
||||
* @param {object} event The event object to check.
|
||||
* @returns {boolean} True if the event is a fullday event, false otherwise
|
||||
*/
|
||||
isFullDayEvent: function (event) {
|
||||
if (event.start.length === 8 || event.start.dateOnly || event.datetype === "date") {
|
||||
return true;
|
||||
}
|
||||
|
||||
const start = event.start || 0;
|
||||
const startDate = new Date(start);
|
||||
const end = event.end || 0;
|
||||
if ((end - start) % (24 * 60 * 60 * 1000) === 0 && startDate.getHours() === 0 && startDate.getMinutes() === 0) {
|
||||
// Is 24 hours, and starts on the middle of the night.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if the user defined time filter should apply
|
||||
*
|
||||
* @param {Date} now Date object using previously created object for consistency
|
||||
* @param {Moment} endDate Moment object representing the event end date
|
||||
* @param {string} filter The time to subtract from the end date to determine if an event should be shown
|
||||
* @returns {boolean} True if the event should be filtered out, false otherwise
|
||||
*/
|
||||
timeFilterApplies: function (now, endDate, filter) {
|
||||
if (filter) {
|
||||
const until = filter.split(" "),
|
||||
value = parseInt(until[0]),
|
||||
increment = until[1].slice(-1) === "s" ? until[1] : until[1] + "s", // Massage the data for moment js
|
||||
filterUntil = moment(endDate.format()).subtract(value, increment);
|
||||
|
||||
return now < filterUntil.format("x");
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if the user defined title filter should apply
|
||||
*
|
||||
* @param {string} title the title of the event
|
||||
* @param {string} filter the string to look for, can be a regex also
|
||||
* @param {boolean} useRegex true if a regex should be used, otherwise it just looks for the filter as a string
|
||||
* @param {string} regexFlags flags that should be applied to the regex
|
||||
* @returns {boolean} True if the title should be filtered out, false otherwise
|
||||
*/
|
||||
titleFilterApplies: function (title, filter, useRegex, regexFlags) {
|
||||
if (useRegex) {
|
||||
// Assume if leading slash, there is also trailing slash
|
||||
if (filter[0] === "/") {
|
||||
// Strip leading and trailing slashes
|
||||
filter = filter.substr(1).slice(0, -1);
|
||||
}
|
||||
|
||||
filter = new RegExp(filter, regexFlags);
|
||||
|
||||
return filter.test(title);
|
||||
} else {
|
||||
return title.includes(filter);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = CalendarUtils;
|
||||
}
|
||||
43
modules/default/calendar/debug.js
Normal file
43
modules/default/calendar/debug.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* CalendarFetcher Tester
|
||||
* use this script with `node debug.js` to test the fetcher without the need
|
||||
* of starting the MagicMirror core. Adjust the values below to your desire.
|
||||
*
|
||||
* By Michael Teeuw https://michaelteeuw.nl
|
||||
* MIT Licensed.
|
||||
*/
|
||||
// Alias modules mentioned in package.js under _moduleAliases.
|
||||
require("module-alias/register");
|
||||
|
||||
const CalendarFetcher = require("./calendarfetcher.js");
|
||||
|
||||
const url = "https://calendar.google.com/calendar/ical/pkm1t2uedjbp0uvq1o7oj1jouo%40group.calendar.google.com/private-08ba559f89eec70dd74bbd887d0a3598/basic.ics"; // Standard test URL
|
||||
//const url = "https://www.googleapis.com/calendar/v3/calendars/primary/events/"; // URL for Bearer auth (must be configured in Google OAuth2 first)
|
||||
const fetchInterval = 60 * 60 * 1000;
|
||||
const maximumEntries = 10;
|
||||
const maximumNumberOfDays = 365;
|
||||
const user = "magicmirror";
|
||||
const pass = "MyStrongPass";
|
||||
const auth = {
|
||||
user: user,
|
||||
pass: pass
|
||||
};
|
||||
|
||||
console.log("Create fetcher ...");
|
||||
|
||||
const fetcher = new CalendarFetcher(url, fetchInterval, [], maximumEntries, maximumNumberOfDays, auth);
|
||||
|
||||
fetcher.onReceive(function (fetcher) {
|
||||
console.log(fetcher.events());
|
||||
console.log("------------------------------------------------------------");
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
fetcher.onError(function (fetcher, error) {
|
||||
console.log("Fetcher error:");
|
||||
console.log(error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
fetcher.startFetch();
|
||||
|
||||
console.log("Create fetcher done! ");
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user