aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package-lock.json213
-rw-r--r--package.json1
-rw-r--r--src/components/settings/services/EditServiceForm.js10
-rw-r--r--src/containers/settings/EditServiceScreen.js40
-rw-r--r--src/containers/settings/EditSettingsScreen.js16
-rw-r--r--src/features/spellchecker/index.js8
-rw-r--r--src/helpers/i18n-helpers.js27
-rw-r--r--src/i18n/globalMessages.js16
-rw-r--r--src/i18n/locales/en-US.json4
-rw-r--r--src/webview/contextMenu.js12
-rw-r--r--src/webview/recipe.js56
-rw-r--r--src/webview/spellchecker.js11
12 files changed, 276 insertions, 138 deletions
diff --git a/package-lock.json b/package-lock.json
index b665aef82..fc9837ccb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "franz", 2 "name": "franz",
3 "version": "5.0.0-beta.24", 3 "version": "5.0.0",
4 "lockfileVersion": 1, 4 "lockfileVersion": 1,
5 "requires": true, 5 "requires": true,
6 "dependencies": { 6 "dependencies": {
@@ -351,23 +351,23 @@
351 } 351 }
352 }, 352 },
353 "@babel/helpers": { 353 "@babel/helpers": {
354 "version": "7.2.0", 354 "version": "7.3.1",
355 "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.2.0.tgz", 355 "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.3.1.tgz",
356 "integrity": "sha512-Fr07N+ea0dMcMN8nFpuK6dUIT7/ivt9yKQdEEnjVS83tG2pHwPi03gYmk/tyuwONnZ+sY+GFFPlWGgCtW1hF9A==", 356 "integrity": "sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA==",
357 "dev": true, 357 "dev": true,
358 "requires": { 358 "requires": {
359 "@babel/template": "^7.1.2", 359 "@babel/template": "^7.1.2",
360 "@babel/traverse": "^7.1.5", 360 "@babel/traverse": "^7.1.5",
361 "@babel/types": "^7.2.0" 361 "@babel/types": "^7.3.0"
362 }, 362 },
363 "dependencies": { 363 "dependencies": {
364 "@babel/generator": { 364 "@babel/generator": {
365 "version": "7.2.0", 365 "version": "7.3.2",
366 "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", 366 "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.2.tgz",
367 "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", 367 "integrity": "sha512-f3QCuPppXxtZOEm5GWPra/uYUjmNQlu9pbAD8D/9jze4pTY83rTtB1igTBSwvkeNlC5gR24zFFkz+2WHLFQhqQ==",
368 "dev": true, 368 "dev": true,
369 "requires": { 369 "requires": {
370 "@babel/types": "^7.2.0", 370 "@babel/types": "^7.3.2",
371 "jsesc": "^2.5.1", 371 "jsesc": "^2.5.1",
372 "lodash": "^4.17.10", 372 "lodash": "^4.17.10",
373 "source-map": "^0.5.0", 373 "source-map": "^0.5.0",
@@ -375,32 +375,32 @@
375 } 375 }
376 }, 376 },
377 "@babel/parser": { 377 "@babel/parser": {
378 "version": "7.2.0", 378 "version": "7.3.2",
379 "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.0.tgz", 379 "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.2.tgz",
380 "integrity": "sha512-M74+GvK4hn1eejD9lZ7967qAwvqTZayQa3g10ag4s9uewgR7TKjeaT0YMyoq+gVfKYABiWZ4MQD701/t5e1Jhg==", 380 "integrity": "sha512-QzNUC2RO1gadg+fs21fi0Uu0OuGNzRKEmgCxoLNzbCdoprLwjfmZwzUrpUNfJPaVRwBpDY47A17yYEGWyRelnQ==",
381 "dev": true 381 "dev": true
382 }, 382 },
383 "@babel/traverse": { 383 "@babel/traverse": {
384 "version": "7.1.6", 384 "version": "7.2.3",
385 "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.1.6.tgz", 385 "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz",
386 "integrity": "sha512-CXedit6GpISz3sC2k2FsGCUpOhUqKdyL0lqNrImQojagnUMXf8hex4AxYFRuMkNGcvJX5QAFGzB5WJQmSv8SiQ==", 386 "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==",
387 "dev": true, 387 "dev": true,
388 "requires": { 388 "requires": {
389 "@babel/code-frame": "^7.0.0", 389 "@babel/code-frame": "^7.0.0",
390 "@babel/generator": "^7.1.6", 390 "@babel/generator": "^7.2.2",
391 "@babel/helper-function-name": "^7.1.0", 391 "@babel/helper-function-name": "^7.1.0",
392 "@babel/helper-split-export-declaration": "^7.0.0", 392 "@babel/helper-split-export-declaration": "^7.0.0",
393 "@babel/parser": "^7.1.6", 393 "@babel/parser": "^7.2.3",
394 "@babel/types": "^7.1.6", 394 "@babel/types": "^7.2.2",
395 "debug": "^4.1.0", 395 "debug": "^4.1.0",
396 "globals": "^11.1.0", 396 "globals": "^11.1.0",
397 "lodash": "^4.17.10" 397 "lodash": "^4.17.10"
398 } 398 }
399 }, 399 },
400 "@babel/types": { 400 "@babel/types": {
401 "version": "7.2.0", 401 "version": "7.3.2",
402 "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.0.tgz", 402 "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.2.tgz",
403 "integrity": "sha512-b4v7dyfApuKDvmPb+O488UlGuR1WbwMXFsO/cyqMrnfvRAChZKJAYeeglWTjUO1b9UghKKgepAQM5tsvBJca6A==", 403 "integrity": "sha512-3Y6H8xlUlpbGR+XvawiH0UXehqydTmNmEpozWcXymqwcrwYAl5KMvKtQ+TF6f6E08V6Jur7v/ykdDSF+WDEIXQ==",
404 "dev": true, 404 "dev": true,
405 "requires": { 405 "requires": {
406 "esutils": "^2.0.2", 406 "esutils": "^2.0.2",
@@ -409,31 +409,19 @@
409 } 409 }
410 }, 410 },
411 "debug": { 411 "debug": {
412 "version": "4.1.0", 412 "version": "4.1.1",
413 "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", 413 "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
414 "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", 414 "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
415 "dev": true, 415 "dev": true,
416 "requires": { 416 "requires": {
417 "ms": "^2.1.1" 417 "ms": "^2.1.1"
418 } 418 }
419 }, 419 },
420 "globals": {
421 "version": "11.9.0",
422 "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz",
423 "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==",
424 "dev": true
425 },
426 "ms": { 420 "ms": {
427 "version": "2.1.1", 421 "version": "2.1.1",
428 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 422 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
429 "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 423 "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
430 "dev": true 424 "dev": true
431 },
432 "to-fast-properties": {
433 "version": "2.0.0",
434 "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
435 "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
436 "dev": true
437 } 425 }
438 } 426 }
439 }, 427 },
@@ -1203,9 +1191,9 @@
1203 } 1191 }
1204 }, 1192 },
1205 "@types/node": { 1193 "@types/node": {
1206 "version": "10.12.23", 1194 "version": "10.12.21",
1207 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.23.tgz", 1195 "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.21.tgz",
1208 "integrity": "sha512-EKhb5NveQ3NlW5EV7B0VRtDKwUfVey8LuJRl9pp5iW0se87/ZqLjG0PMf2MCzPXAJYWZN5Ltg7pHIAf9/Dm1tQ==", 1196 "integrity": "sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ==",
1209 "dev": true 1197 "dev": true
1210 }, 1198 },
1211 "JSONStream": { 1199 "JSONStream": {
@@ -1236,7 +1224,7 @@
1236 "dependencies": { 1224 "dependencies": {
1237 "mime-types": { 1225 "mime-types": {
1238 "version": "1.0.2", 1226 "version": "1.0.2",
1239 "resolved": "http://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", 1227 "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz",
1240 "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", 1228 "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=",
1241 "dev": true 1229 "dev": true
1242 } 1230 }
@@ -1342,7 +1330,7 @@
1342 }, 1330 },
1343 "ansi-colors": { 1331 "ansi-colors": {
1344 "version": "1.1.0", 1332 "version": "1.1.0",
1345 "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", 1333 "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
1346 "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", 1334 "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==",
1347 "dev": true, 1335 "dev": true,
1348 "requires": { 1336 "requires": {
@@ -1698,7 +1686,7 @@
1698 }, 1686 },
1699 "async": { 1687 "async": {
1700 "version": "0.1.22", 1688 "version": "0.1.22",
1701 "resolved": "http://registry.npmjs.org/async/-/async-0.1.22.tgz", 1689 "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz",
1702 "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=" 1690 "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE="
1703 }, 1691 },
1704 "async-done": { 1692 "async-done": {
@@ -2487,6 +2475,16 @@
2487 "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", 2475 "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
2488 "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" 2476 "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
2489 }, 2477 },
2478 "cld3-asm": {
2479 "version": "1.0.1",
2480 "resolved": "https://registry.npmjs.org/cld3-asm/-/cld3-asm-1.0.1.tgz",
2481 "integrity": "sha512-wuAqZd44Rk164TLKSYyLFZGSObhf82udOR+M/CnOkeEShq9+Tpxb/9RAE0m/KUVD1DnR5gMkZFeYExt51PCAbg==",
2482 "requires": {
2483 "emscripten-wasm-loader": "^1.0.0",
2484 "tslib": "^1.9.0",
2485 "utf8": "^3.0.0"
2486 }
2487 },
2490 "cli-boxes": { 2488 "cli-boxes": {
2491 "version": "1.0.0", 2489 "version": "1.0.0",
2492 "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", 2490 "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
@@ -3024,7 +3022,7 @@
3024 "dependencies": { 3022 "dependencies": {
3025 "debug": { 3023 "debug": {
3026 "version": "1.0.4", 3024 "version": "1.0.4",
3027 "resolved": "http://registry.npmjs.org/debug/-/debug-1.0.4.tgz", 3025 "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz",
3028 "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=", 3026 "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=",
3029 "dev": true, 3027 "dev": true,
3030 "requires": { 3028 "requires": {
@@ -3033,7 +3031,7 @@
3033 }, 3031 },
3034 "ms": { 3032 "ms": {
3035 "version": "0.6.2", 3033 "version": "0.6.2",
3036 "resolved": "http://registry.npmjs.org/ms/-/ms-0.6.2.tgz", 3034 "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
3037 "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", 3035 "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=",
3038 "dev": true 3036 "dev": true
3039 } 3037 }
@@ -4134,7 +4132,7 @@
4134 "dependencies": { 4132 "dependencies": {
4135 "domelementtype": { 4133 "domelementtype": {
4136 "version": "1.1.3", 4134 "version": "1.1.3",
4137 "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", 4135 "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
4138 "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" 4136 "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
4139 } 4137 }
4140 } 4138 }
@@ -4172,7 +4170,7 @@
4172 }, 4170 },
4173 "dotenv": { 4171 "dotenv": {
4174 "version": "4.0.0", 4172 "version": "4.0.0",
4175 "resolved": "http://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", 4173 "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz",
4176 "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", 4174 "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=",
4177 "dev": true 4175 "dev": true
4178 }, 4176 },
@@ -4207,7 +4205,7 @@
4207 }, 4205 },
4208 "readable-stream": { 4206 "readable-stream": {
4209 "version": "1.1.14", 4207 "version": "1.1.14",
4210 "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 4208 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
4211 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 4209 "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
4212 "dev": true, 4210 "dev": true,
4213 "requires": { 4211 "requires": {
@@ -4829,7 +4827,7 @@
4829 }, 4827 },
4830 "debug": { 4828 "debug": {
4831 "version": "2.3.3", 4829 "version": "2.3.3",
4832 "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", 4830 "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
4833 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", 4831 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
4834 "dev": true, 4832 "dev": true,
4835 "requires": { 4833 "requires": {
@@ -4838,7 +4836,7 @@
4838 }, 4836 },
4839 "ms": { 4837 "ms": {
4840 "version": "0.7.2", 4838 "version": "0.7.2",
4841 "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 4839 "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
4842 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 4840 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
4843 "dev": true 4841 "dev": true
4844 }, 4842 },
@@ -4872,7 +4870,7 @@
4872 "dependencies": { 4870 "dependencies": {
4873 "debug": { 4871 "debug": {
4874 "version": "2.3.3", 4872 "version": "2.3.3",
4875 "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", 4873 "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
4876 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", 4874 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
4877 "dev": true, 4875 "dev": true,
4878 "requires": { 4876 "requires": {
@@ -4881,7 +4879,7 @@
4881 }, 4879 },
4882 "ms": { 4880 "ms": {
4883 "version": "0.7.2", 4881 "version": "0.7.2",
4884 "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 4882 "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
4885 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 4883 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
4886 "dev": true 4884 "dev": true
4887 } 4885 }
@@ -5221,7 +5219,7 @@
5221 }, 5219 },
5222 "load-json-file": { 5220 "load-json-file": {
5223 "version": "2.0.0", 5221 "version": "2.0.0",
5224 "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", 5222 "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
5225 "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", 5223 "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
5226 "dev": true, 5224 "dev": true,
5227 "requires": { 5225 "requires": {
@@ -5725,7 +5723,7 @@
5725 }, 5723 },
5726 "finalhandler": { 5724 "finalhandler": {
5727 "version": "0.1.0", 5725 "version": "0.1.0",
5728 "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-0.1.0.tgz", 5726 "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.1.0.tgz",
5729 "integrity": "sha1-2gW7xPX0owyEzh2R88FUAHxOnao=", 5727 "integrity": "sha1-2gW7xPX0owyEzh2R88FUAHxOnao=",
5730 "dev": true, 5728 "dev": true,
5731 "requires": { 5729 "requires": {
@@ -5735,7 +5733,7 @@
5735 "dependencies": { 5733 "dependencies": {
5736 "debug": { 5734 "debug": {
5737 "version": "1.0.4", 5735 "version": "1.0.4",
5738 "resolved": "http://registry.npmjs.org/debug/-/debug-1.0.4.tgz", 5736 "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz",
5739 "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=", 5737 "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=",
5740 "dev": true, 5738 "dev": true,
5741 "requires": { 5739 "requires": {
@@ -5744,7 +5742,7 @@
5744 }, 5742 },
5745 "ms": { 5743 "ms": {
5746 "version": "0.6.2", 5744 "version": "0.6.2",
5747 "resolved": "http://registry.npmjs.org/ms/-/ms-0.6.2.tgz", 5745 "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
5748 "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", 5746 "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=",
5749 "dev": true 5747 "dev": true
5750 } 5748 }
@@ -5982,13 +5980,15 @@
5982 "version": "1.0.0", 5980 "version": "1.0.0",
5983 "resolved": false, 5981 "resolved": false,
5984 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 5982 "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
5985 "dev": true 5983 "dev": true,
5984 "optional": true
5986 }, 5985 },
5987 "brace-expansion": { 5986 "brace-expansion": {
5988 "version": "1.1.11", 5987 "version": "1.1.11",
5989 "resolved": false, 5988 "resolved": false,
5990 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 5989 "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
5991 "dev": true, 5990 "dev": true,
5991 "optional": true,
5992 "requires": { 5992 "requires": {
5993 "balanced-match": "^1.0.0", 5993 "balanced-match": "^1.0.0",
5994 "concat-map": "0.0.1" 5994 "concat-map": "0.0.1"
@@ -6005,19 +6005,22 @@
6005 "version": "1.1.0", 6005 "version": "1.1.0",
6006 "resolved": false, 6006 "resolved": false,
6007 "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 6007 "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
6008 "dev": true 6008 "dev": true,
6009 "optional": true
6009 }, 6010 },
6010 "concat-map": { 6011 "concat-map": {
6011 "version": "0.0.1", 6012 "version": "0.0.1",
6012 "resolved": false, 6013 "resolved": false,
6013 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 6014 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
6014 "dev": true 6015 "dev": true,
6016 "optional": true
6015 }, 6017 },
6016 "console-control-strings": { 6018 "console-control-strings": {
6017 "version": "1.1.0", 6019 "version": "1.1.0",
6018 "resolved": false, 6020 "resolved": false,
6019 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", 6021 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
6020 "dev": true 6022 "dev": true,
6023 "optional": true
6021 }, 6024 },
6022 "core-util-is": { 6025 "core-util-is": {
6023 "version": "1.0.2", 6026 "version": "1.0.2",
@@ -6148,7 +6151,8 @@
6148 "version": "2.0.3", 6151 "version": "2.0.3",
6149 "resolved": false, 6152 "resolved": false,
6150 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 6153 "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
6151 "dev": true 6154 "dev": true,
6155 "optional": true
6152 }, 6156 },
6153 "ini": { 6157 "ini": {
6154 "version": "1.3.5", 6158 "version": "1.3.5",
@@ -6162,6 +6166,7 @@
6162 "resolved": false, 6166 "resolved": false,
6163 "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 6167 "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
6164 "dev": true, 6168 "dev": true,
6169 "optional": true,
6165 "requires": { 6170 "requires": {
6166 "number-is-nan": "^1.0.0" 6171 "number-is-nan": "^1.0.0"
6167 } 6172 }
@@ -6178,6 +6183,7 @@
6178 "resolved": false, 6183 "resolved": false,
6179 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 6184 "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
6180 "dev": true, 6185 "dev": true,
6186 "optional": true,
6181 "requires": { 6187 "requires": {
6182 "brace-expansion": "^1.1.7" 6188 "brace-expansion": "^1.1.7"
6183 } 6189 }
@@ -6186,13 +6192,15 @@
6186 "version": "0.0.8", 6192 "version": "0.0.8",
6187 "resolved": false, 6193 "resolved": false,
6188 "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 6194 "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
6189 "dev": true 6195 "dev": true,
6196 "optional": true
6190 }, 6197 },
6191 "minipass": { 6198 "minipass": {
6192 "version": "2.2.4", 6199 "version": "2.2.4",
6193 "resolved": false, 6200 "resolved": false,
6194 "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", 6201 "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
6195 "dev": true, 6202 "dev": true,
6203 "optional": true,
6196 "requires": { 6204 "requires": {
6197 "safe-buffer": "^5.1.1", 6205 "safe-buffer": "^5.1.1",
6198 "yallist": "^3.0.0" 6206 "yallist": "^3.0.0"
@@ -6213,6 +6221,7 @@
6213 "resolved": false, 6221 "resolved": false,
6214 "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 6222 "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
6215 "dev": true, 6223 "dev": true,
6224 "optional": true,
6216 "requires": { 6225 "requires": {
6217 "minimist": "0.0.8" 6226 "minimist": "0.0.8"
6218 } 6227 }
@@ -6301,7 +6310,8 @@
6301 "version": "1.0.1", 6310 "version": "1.0.1",
6302 "resolved": false, 6311 "resolved": false,
6303 "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 6312 "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
6304 "dev": true 6313 "dev": true,
6314 "optional": true
6305 }, 6315 },
6306 "object-assign": { 6316 "object-assign": {
6307 "version": "4.1.1", 6317 "version": "4.1.1",
@@ -6315,6 +6325,7 @@
6315 "resolved": false, 6325 "resolved": false,
6316 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 6326 "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
6317 "dev": true, 6327 "dev": true,
6328 "optional": true,
6318 "requires": { 6329 "requires": {
6319 "wrappy": "1" 6330 "wrappy": "1"
6320 } 6331 }
@@ -6452,6 +6463,7 @@
6452 "resolved": false, 6463 "resolved": false,
6453 "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 6464 "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
6454 "dev": true, 6465 "dev": true,
6466 "optional": true,
6455 "requires": { 6467 "requires": {
6456 "code-point-at": "^1.0.0", 6468 "code-point-at": "^1.0.0",
6457 "is-fullwidth-code-point": "^1.0.0", 6469 "is-fullwidth-code-point": "^1.0.0",
@@ -7153,7 +7165,7 @@
7153 }, 7165 },
7154 "got": { 7166 "got": {
7155 "version": "6.7.1", 7167 "version": "6.7.1",
7156 "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", 7168 "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
7157 "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", 7169 "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
7158 "dev": true, 7170 "dev": true,
7159 "requires": { 7171 "requires": {
@@ -7388,7 +7400,7 @@
7388 }, 7400 },
7389 "yargs": { 7401 "yargs": {
7390 "version": "3.32.0", 7402 "version": "3.32.0",
7391 "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", 7403 "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
7392 "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", 7404 "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
7393 "requires": { 7405 "requires": {
7394 "camelcase": "^2.0.1", 7406 "camelcase": "^2.0.1",
@@ -7608,7 +7620,7 @@
7608 }, 7620 },
7609 "lodash": { 7621 "lodash": {
7610 "version": "1.0.2", 7622 "version": "1.0.2",
7611 "resolved": "http://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", 7623 "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz",
7612 "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", 7624 "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=",
7613 "dev": true 7625 "dev": true
7614 }, 7626 },
@@ -7668,7 +7680,7 @@
7668 }, 7680 },
7669 "readable-stream": { 7681 "readable-stream": {
7670 "version": "1.0.34", 7682 "version": "1.0.34",
7671 "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 7683 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
7672 "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 7684 "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
7673 "dev": true, 7685 "dev": true,
7674 "requires": { 7686 "requires": {
@@ -7830,9 +7842,9 @@
7830 } 7842 }
7831 }, 7843 },
7832 "handlebars": { 7844 "handlebars": {
7833 "version": "4.0.12", 7845 "version": "4.1.0",
7834 "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", 7846 "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz",
7835 "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", 7847 "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==",
7836 "dev": true, 7848 "dev": true,
7837 "requires": { 7849 "requires": {
7838 "async": "^2.5.0", 7850 "async": "^2.5.0",
@@ -8060,7 +8072,7 @@
8060 }, 8072 },
8061 "hunspell-asm": { 8073 "hunspell-asm": {
8062 "version": "1.0.2", 8074 "version": "1.0.2",
8063 "resolved": "http://registry.npmjs.org/hunspell-asm/-/hunspell-asm-1.0.2.tgz", 8075 "resolved": "https://registry.npmjs.org/hunspell-asm/-/hunspell-asm-1.0.2.tgz",
8064 "integrity": "sha512-UTLBvc0yZiIcHl9qrgxnFTZbX3zF4CprzEY+u+N0iXlUKZnUJRIgvgppTdgiQTsucm5b0aN/rHsgXz2q/0kBRA==", 8076 "integrity": "sha512-UTLBvc0yZiIcHl9qrgxnFTZbX3zF4CprzEY+u+N0iXlUKZnUJRIgvgppTdgiQTsucm5b0aN/rHsgXz2q/0kBRA==",
8065 "requires": { 8077 "requires": {
8066 "emscripten-wasm-loader": "^1.0.0", 8078 "emscripten-wasm-loader": "^1.0.0",
@@ -8475,7 +8487,7 @@
8475 }, 8487 },
8476 "is": { 8488 "is": {
8477 "version": "0.3.0", 8489 "version": "0.3.0",
8478 "resolved": "http://registry.npmjs.org/is/-/is-0.3.0.tgz", 8490 "resolved": "https://registry.npmjs.org/is/-/is-0.3.0.tgz",
8479 "integrity": "sha1-qPcd/IpuKDcWJ/JskpCYxvTV1dc=", 8491 "integrity": "sha1-qPcd/IpuKDcWJ/JskpCYxvTV1dc=",
8480 "dev": true 8492 "dev": true
8481 }, 8493 },
@@ -8698,7 +8710,7 @@
8698 }, 8710 },
8699 "is-obj": { 8711 "is-obj": {
8700 "version": "1.0.1", 8712 "version": "1.0.1",
8701 "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", 8713 "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
8702 "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", 8714 "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
8703 "dev": true 8715 "dev": true
8704 }, 8716 },
@@ -8845,7 +8857,7 @@
8845 }, 8857 },
8846 "isemail": { 8858 "isemail": {
8847 "version": "1.2.0", 8859 "version": "1.2.0",
8848 "resolved": "http://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", 8860 "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
8849 "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" 8861 "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo="
8850 }, 8862 },
8851 "isexe": { 8863 "isexe": {
@@ -8875,7 +8887,7 @@
8875 }, 8887 },
8876 "joi": { 8888 "joi": {
8877 "version": "6.10.1", 8889 "version": "6.10.1",
8878 "resolved": "http://registry.npmjs.org/joi/-/joi-6.10.1.tgz", 8890 "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz",
8879 "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", 8891 "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=",
8880 "requires": { 8892 "requires": {
8881 "hoek": "2.x.x", 8893 "hoek": "2.x.x",
@@ -9695,7 +9707,7 @@
9695 }, 9707 },
9696 "readable-stream": { 9708 "readable-stream": {
9697 "version": "1.0.34", 9709 "version": "1.0.34",
9698 "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 9710 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
9699 "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 9711 "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
9700 "dev": true, 9712 "dev": true,
9701 "requires": { 9713 "requires": {
@@ -9778,7 +9790,7 @@
9778 }, 9790 },
9779 "minimist": { 9791 "minimist": {
9780 "version": "1.2.0", 9792 "version": "1.2.0",
9781 "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 9793 "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
9782 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 9794 "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
9783 }, 9795 },
9784 "minimist-options": { 9796 "minimist-options": {
@@ -9836,7 +9848,7 @@
9836 }, 9848 },
9837 "mkdirp": { 9849 "mkdirp": {
9838 "version": "0.5.1", 9850 "version": "0.5.1",
9839 "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 9851 "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
9840 "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 9852 "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
9841 "requires": { 9853 "requires": {
9842 "minimist": "0.0.8" 9854 "minimist": "0.0.8"
@@ -9844,7 +9856,7 @@
9844 "dependencies": { 9856 "dependencies": {
9845 "minimist": { 9857 "minimist": {
9846 "version": "0.0.8", 9858 "version": "0.0.8",
9847 "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 9859 "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
9848 "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 9860 "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
9849 } 9861 }
9850 } 9862 }
@@ -10032,7 +10044,7 @@
10032 "dependencies": { 10044 "dependencies": {
10033 "semver": { 10045 "semver": {
10034 "version": "5.3.0", 10046 "version": "5.3.0",
10035 "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 10047 "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
10036 "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", 10048 "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
10037 "dev": true 10049 "dev": true
10038 }, 10050 },
@@ -13701,7 +13713,7 @@
13701 "dependencies": { 13713 "dependencies": {
13702 "color-convert": { 13714 "color-convert": {
13703 "version": "0.5.3", 13715 "version": "0.5.3",
13704 "resolved": "http://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", 13716 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
13705 "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", 13717 "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=",
13706 "dev": true 13718 "dev": true
13707 } 13719 }
@@ -13979,7 +13991,7 @@
13979 }, 13991 },
13980 "pretty-hrtime": { 13992 "pretty-hrtime": {
13981 "version": "1.0.3", 13993 "version": "1.0.3",
13982 "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", 13994 "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
13983 "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" 13995 "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE="
13984 }, 13996 },
13985 "private": { 13997 "private": {
@@ -14302,7 +14314,7 @@
14302 }, 14314 },
14303 "react-router": { 14315 "react-router": {
14304 "version": "3.2.1", 14316 "version": "3.2.1",
14305 "resolved": "http://registry.npmjs.org/react-router/-/react-router-3.2.1.tgz", 14317 "resolved": "https://registry.npmjs.org/react-router/-/react-router-3.2.1.tgz",
14306 "integrity": "sha512-SXkhC0nr3G0ltzVU07IN8jYl0bB6FsrDIqlLC9dK3SITXqyTJyM7yhXlUqs89w3Nqi5OkXsfRUeHX+P874HQrg==", 14318 "integrity": "sha512-SXkhC0nr3G0ltzVU07IN8jYl0bB6FsrDIqlLC9dK3SITXqyTJyM7yhXlUqs89w3Nqi5OkXsfRUeHX+P874HQrg==",
14307 "requires": { 14319 "requires": {
14308 "create-react-class": "^15.5.1", 14320 "create-react-class": "^15.5.1",
@@ -14955,7 +14967,7 @@
14955 "dependencies": { 14967 "dependencies": {
14956 "debug": { 14968 "debug": {
14957 "version": "1.0.4", 14969 "version": "1.0.4",
14958 "resolved": "http://registry.npmjs.org/debug/-/debug-1.0.4.tgz", 14970 "resolved": "https://registry.npmjs.org/debug/-/debug-1.0.4.tgz",
14959 "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=", 14971 "integrity": "sha1-W5wla9VLbsAigxdvqKDt5tFUy/g=",
14960 "dev": true, 14972 "dev": true,
14961 "requires": { 14973 "requires": {
@@ -14970,7 +14982,7 @@
14970 }, 14982 },
14971 "ms": { 14983 "ms": {
14972 "version": "0.6.2", 14984 "version": "0.6.2",
14973 "resolved": "http://registry.npmjs.org/ms/-/ms-0.6.2.tgz", 14985 "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz",
14974 "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", 14986 "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=",
14975 "dev": true 14987 "dev": true
14976 } 14988 }
@@ -15220,7 +15232,7 @@
15220 "dependencies": { 15232 "dependencies": {
15221 "debug": { 15233 "debug": {
15222 "version": "2.3.3", 15234 "version": "2.3.3",
15223 "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", 15235 "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
15224 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", 15236 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
15225 "dev": true, 15237 "dev": true,
15226 "requires": { 15238 "requires": {
@@ -15229,7 +15241,7 @@
15229 }, 15241 },
15230 "ms": { 15242 "ms": {
15231 "version": "0.7.2", 15243 "version": "0.7.2",
15232 "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 15244 "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
15233 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 15245 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
15234 "dev": true 15246 "dev": true
15235 }, 15247 },
@@ -15253,7 +15265,7 @@
15253 "dependencies": { 15265 "dependencies": {
15254 "debug": { 15266 "debug": {
15255 "version": "2.3.3", 15267 "version": "2.3.3",
15256 "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", 15268 "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
15257 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", 15269 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
15258 "dev": true, 15270 "dev": true,
15259 "requires": { 15271 "requires": {
@@ -15262,7 +15274,7 @@
15262 }, 15274 },
15263 "ms": { 15275 "ms": {
15264 "version": "0.7.2", 15276 "version": "0.7.2",
15265 "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 15277 "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
15266 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 15278 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
15267 "dev": true 15279 "dev": true
15268 } 15280 }
@@ -15289,7 +15301,7 @@
15289 "dependencies": { 15301 "dependencies": {
15290 "debug": { 15302 "debug": {
15291 "version": "2.3.3", 15303 "version": "2.3.3",
15292 "resolved": "http://registry.npmjs.org/debug/-/debug-2.3.3.tgz", 15304 "resolved": "https://registry.npmjs.org/debug/-/debug-2.3.3.tgz",
15293 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=", 15305 "integrity": "sha1-QMRT5n5uE8kB3ewxeviYbNqe/4w=",
15294 "dev": true, 15306 "dev": true,
15295 "requires": { 15307 "requires": {
@@ -15298,7 +15310,7 @@
15298 }, 15310 },
15299 "ms": { 15311 "ms": {
15300 "version": "0.7.2", 15312 "version": "0.7.2",
15301 "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 15313 "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz",
15302 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 15314 "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=",
15303 "dev": true 15315 "dev": true
15304 } 15316 }
@@ -15324,7 +15336,7 @@
15324 }, 15336 },
15325 "debug": { 15337 "debug": {
15326 "version": "2.2.0", 15338 "version": "2.2.0",
15327 "resolved": "http://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 15339 "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
15328 "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", 15340 "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
15329 "dev": true, 15341 "dev": true,
15330 "requires": { 15342 "requires": {
@@ -15339,7 +15351,7 @@
15339 }, 15351 },
15340 "ms": { 15352 "ms": {
15341 "version": "0.7.1", 15353 "version": "0.7.1",
15342 "resolved": "http://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 15354 "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
15343 "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", 15355 "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
15344 "dev": true 15356 "dev": true
15345 } 15357 }
@@ -15813,7 +15825,7 @@
15813 }, 15825 },
15814 "through": { 15826 "through": {
15815 "version": "2.3.8", 15827 "version": "2.3.8",
15816 "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", 15828 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
15817 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 15829 "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
15818 "dev": true 15830 "dev": true
15819 }, 15831 },
@@ -15881,6 +15893,12 @@
15881 "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", 15893 "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
15882 "dev": true 15894 "dev": true
15883 }, 15895 },
15896 "to-fast-properties": {
15897 "version": "2.0.0",
15898 "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
15899 "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
15900 "dev": true
15901 },
15884 "to-object-path": { 15902 "to-object-path": {
15885 "version": "0.3.0", 15903 "version": "0.3.0",
15886 "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", 15904 "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
@@ -16340,6 +16358,11 @@
16340 "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", 16358 "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
16341 "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" 16359 "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA="
16342 }, 16360 },
16361 "utf8": {
16362 "version": "3.0.0",
16363 "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz",
16364 "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ=="
16365 },
16343 "utf8-byte-length": { 16366 "utf8-byte-length": {
16344 "version": "1.0.4", 16367 "version": "1.0.4",
16345 "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", 16368 "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
@@ -16643,7 +16666,7 @@
16643 }, 16666 },
16644 "wrap-ansi": { 16667 "wrap-ansi": {
16645 "version": "2.1.0", 16668 "version": "2.1.0",
16646 "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 16669 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
16647 "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 16670 "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
16648 "requires": { 16671 "requires": {
16649 "string-width": "^1.0.1", 16672 "string-width": "^1.0.1",
@@ -16708,7 +16731,7 @@
16708 }, 16731 },
16709 "xmlbuilder": { 16732 "xmlbuilder": {
16710 "version": "9.0.7", 16733 "version": "9.0.7",
16711 "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 16734 "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
16712 "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", 16735 "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
16713 "dev": true 16736 "dev": true
16714 }, 16737 },
diff --git a/package.json b/package.json
index 8ece958ee..633fa678f 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
34 "address-rfc2822": "^2.0.1", 34 "address-rfc2822": "^2.0.1",
35 "auto-launch": "https://github.com/meetfranz/node-auto-launch.git", 35 "auto-launch": "https://github.com/meetfranz/node-auto-launch.git",
36 "classnames": "2.2.6", 36 "classnames": "2.2.6",
37 "cld3-asm": "1.0.1",
37 "debug-electron": "^0.0.4", 38 "debug-electron": "^0.0.4",
38 "du": "^0.1.0", 39 "du": "^0.1.0",
39 "electron-dl": "1.12.0", 40 "electron-dl": "1.12.0",
diff --git a/src/components/settings/services/EditServiceForm.js b/src/components/settings/services/EditServiceForm.js
index 468d85c45..21616b5de 100644
--- a/src/components/settings/services/EditServiceForm.js
+++ b/src/components/settings/services/EditServiceForm.js
@@ -128,7 +128,8 @@ export default @observer class EditServiceForm extends Component {
128 isSaving: PropTypes.bool.isRequired, 128 isSaving: PropTypes.bool.isRequired,
129 isDeleting: PropTypes.bool.isRequired, 129 isDeleting: PropTypes.bool.isRequired,
130 isProxyFeatureEnabled: PropTypes.bool.isRequired, 130 isProxyFeatureEnabled: PropTypes.bool.isRequired,
131 isProxyFeaturePremiumFeature: PropTypes.bool.isRequired, 131 isProxyPremiumFeature: PropTypes.bool.isRequired,
132 isSpellcheckerPremiumFeature: PropTypes.bool.isRequired,
132 }; 133 };
133 134
134 static defaultProps = { 135 static defaultProps = {
@@ -191,7 +192,8 @@ export default @observer class EditServiceForm extends Component {
191 isDeleting, 192 isDeleting,
192 onDelete, 193 onDelete,
193 isProxyFeatureEnabled, 194 isProxyFeatureEnabled,
194 isProxyFeaturePremiumFeature, 195 isProxyPremiumFeature,
196 isSpellcheckerPremiumFeature,
195 } = this.props; 197 } = this.props;
196 const { intl } = this.context; 198 const { intl } = this.context;
197 199
@@ -339,14 +341,14 @@ export default @observer class EditServiceForm extends Component {
339 </div> 341 </div>
340 </div> 342 </div>
341 343
342 <PremiumFeatureContainer> 344 <PremiumFeatureContainer condition={isSpellcheckerPremiumFeature}>
343 <div className="settings__settings-group"> 345 <div className="settings__settings-group">
344 <Select field={form.$('spellcheckerLanguage')} /> 346 <Select field={form.$('spellcheckerLanguage')} />
345 </div> 347 </div>
346 </PremiumFeatureContainer> 348 </PremiumFeatureContainer>
347 349
348 {isProxyFeatureEnabled && ( 350 {isProxyFeatureEnabled && (
349 <PremiumFeatureContainer condition={isProxyFeaturePremiumFeature}> 351 <PremiumFeatureContainer condition={isProxyPremiumFeature}>
350 <div className="settings__settings-group"> 352 <div className="settings__settings-group">
351 <h3> 353 <h3>
352 {intl.formatMessage(messages.headlineProxy)} 354 {intl.formatMessage(messages.headlineProxy)}
diff --git a/src/containers/settings/EditServiceScreen.js b/src/containers/settings/EditServiceScreen.js
index b46908344..d08f0a52e 100644
--- a/src/containers/settings/EditServiceScreen.js
+++ b/src/containers/settings/EditServiceScreen.js
@@ -19,9 +19,12 @@ import { required, url, oneRequired } from '../../helpers/validation-helpers';
19import { getSelectOptions } from '../../helpers/i18n-helpers'; 19import { getSelectOptions } from '../../helpers/i18n-helpers';
20 20
21import { config as proxyFeature } from '../../features/serviceProxy'; 21import { config as proxyFeature } from '../../features/serviceProxy';
22import { config as spellcheckerFeature } from '../../features/spellchecker';
22 23
23import { SPELLCHECKER_LOCALES } from '../../i18n/languages'; 24import { SPELLCHECKER_LOCALES } from '../../i18n/languages';
24 25
26import globalMessages from '../../i18n/globalMessages';
27
25const messages = defineMessages({ 28const messages = defineMessages({
26 name: { 29 name: {
27 id: 'settings.service.form.name', 30 id: 'settings.service.form.name',
@@ -83,14 +86,6 @@ const messages = defineMessages({
83 id: 'settings.service.form.proxy.password', 86 id: 'settings.service.form.proxy.password',
84 defaultMessage: '!!!Password', 87 defaultMessage: '!!!Password',
85 }, 88 },
86 spellcheckerLanguage: {
87 id: 'settings.service.form.spellcheckerLanguage',
88 defaultMessage: '!!!Spell checking Language',
89 },
90 spellcheckerSystemDefault: {
91 id: 'settings.service.form.spellcheckerLanguage.default',
92 defaultMessage: '!!!Use System Default ({default})',
93 },
94}); 89});
95 90
96export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component { 91export default @inject('stores', 'actions') @observer class EditServiceScreen extends Component {
@@ -118,12 +113,26 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
118 } 113 }
119 114
120 prepareForm(recipe, service, proxy) { 115 prepareForm(recipe, service, proxy) {
116 const {
117 intl,
118 } = this.context;
119
120 const {
121 stores,
122 } = this.props;
123
124 let defaultSpellcheckerLanguage = SPELLCHECKER_LOCALES[stores.settings.app.spellcheckerLanguage];
125
126 if (stores.settings.app.spellcheckerLanguage === 'automatic') {
127 defaultSpellcheckerLanguage = intl.formatMessage(globalMessages.spellcheckerAutomaticDetectionShort);
128 }
129
121 const spellcheckerLanguage = getSelectOptions({ 130 const spellcheckerLanguage = getSelectOptions({
122 locales: SPELLCHECKER_LOCALES, 131 locales: SPELLCHECKER_LOCALES,
123 resetToDefaultText: this.context.intl.formatMessage(messages.spellcheckerSystemDefault, { default: SPELLCHECKER_LOCALES[this.props.stores.settings.app.spellcheckerLanguage] }), 132 resetToDefaultText: intl.formatMessage(globalMessages.spellcheckerSystemDefault, { default: defaultSpellcheckerLanguage }),
133 automaticDetectionText: stores.settings.app.spellcheckerLanguage !== 'automatic' ? intl.formatMessage(globalMessages.spellcheckerAutomaticDetection) : '',
124 }); 134 });
125 135
126 const { intl } = this.context;
127 const config = { 136 const config = {
128 fields: { 137 fields: {
129 name: { 138 name: {
@@ -160,13 +169,13 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
160 isDarkModeEnabled: { 169 isDarkModeEnabled: {
161 label: intl.formatMessage(messages.enableDarkMode), 170 label: intl.formatMessage(messages.enableDarkMode),
162 value: service.isDarkModeEnabled, 171 value: service.isDarkModeEnabled,
163 default: this.props.stores.settings.app.darkMode, 172 default: stores.settings.app.darkMode,
164 }, 173 },
165 spellcheckerLanguage: { 174 spellcheckerLanguage: {
166 label: intl.formatMessage(messages.spellcheckerLanguage), 175 label: intl.formatMessage(globalMessages.spellcheckerLanguage),
167 value: service.spellcheckerLanguage, 176 value: service.spellcheckerLanguage,
168 options: spellcheckerLanguage, 177 options: spellcheckerLanguage,
169 disabled: !this.props.stores.settings.app.enableSpellchecking, 178 disabled: !stores.settings.app.enableSpellchecking,
170 }, 179 },
171 }, 180 },
172 }; 181 };
@@ -220,7 +229,7 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
220 } 229 }
221 230
222 if (proxy.isEnabled) { 231 if (proxy.isEnabled) {
223 const serviceProxyConfig = this.props.stores.settings.proxy[service.id] || {}; 232 const serviceProxyConfig = stores.settings.proxy[service.id] || {};
224 233
225 Object.assign(config.fields, { 234 Object.assign(config.fields, {
226 proxy: { 235 proxy: {
@@ -326,7 +335,8 @@ export default @inject('stores', 'actions') @observer class EditServiceScreen ex
326 onSubmit={d => this.onSubmit(d)} 335 onSubmit={d => this.onSubmit(d)}
327 onDelete={() => this.deleteService()} 336 onDelete={() => this.deleteService()}
328 isProxyFeatureEnabled={proxyFeature.isEnabled} 337 isProxyFeatureEnabled={proxyFeature.isEnabled}
329 isProxyFeaturePremiumFeature={proxyFeature.isPremium} 338 isProxyPremiumFeature={proxyFeature.isPremium}
339 isSpellcheckerPremiumFeature={spellcheckerFeature.isPremium}
330 /> 340 />
331 </ErrorBoundary> 341 </ErrorBoundary>
332 ); 342 );
diff --git a/src/containers/settings/EditSettingsScreen.js b/src/containers/settings/EditSettingsScreen.js
index f1706a721..992c49b09 100644
--- a/src/containers/settings/EditSettingsScreen.js
+++ b/src/containers/settings/EditSettingsScreen.js
@@ -14,10 +14,11 @@ import { config as spellcheckerConfig } from '../../features/spellchecker';
14 14
15import { getSelectOptions } from '../../helpers/i18n-helpers'; 15import { getSelectOptions } from '../../helpers/i18n-helpers';
16 16
17
18import EditSettingsForm from '../../components/settings/settings/EditSettingsForm'; 17import EditSettingsForm from '../../components/settings/settings/EditSettingsForm';
19import ErrorBoundary from '../../components/util/ErrorBoundary'; 18import ErrorBoundary from '../../components/util/ErrorBoundary';
20 19
20import globalMessages from '../../i18n/globalMessages';
21
21const messages = defineMessages({ 22const messages = defineMessages({
22 autoLaunchOnStart: { 23 autoLaunchOnStart: {
23 id: 'settings.app.form.autoLaunchOnStart', 24 id: 'settings.app.form.autoLaunchOnStart',
@@ -63,10 +64,6 @@ const messages = defineMessages({
63 id: 'settings.app.form.enableGPUAcceleration', 64 id: 'settings.app.form.enableGPUAcceleration',
64 defaultMessage: '!!!Enable GPU Acceleration', 65 defaultMessage: '!!!Enable GPU Acceleration',
65 }, 66 },
66 spellcheckerLanguage: {
67 id: 'settings.app.form.spellcheckerLanguage',
68 defaultMessage: '!!!Language for spell checking',
69 },
70 beta: { 67 beta: {
71 id: 'settings.app.form.beta', 68 id: 'settings.app.form.beta',
72 defaultMessage: '!!!Include beta versions', 69 defaultMessage: '!!!Include beta versions',
@@ -125,6 +122,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
125 122
126 const spellcheckingLanguages = getSelectOptions({ 123 const spellcheckingLanguages = getSelectOptions({
127 locales: SPELLCHECKER_LOCALES, 124 locales: SPELLCHECKER_LOCALES,
125 automaticDetectionText: this.context.intl.formatMessage(globalMessages.spellcheckerAutomaticDetection),
128 }); 126 });
129 127
130 const config = { 128 const config = {
@@ -166,11 +164,11 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
166 }, 164 },
167 enableSpellchecking: { 165 enableSpellchecking: {
168 label: intl.formatMessage(messages.enableSpellchecking), 166 label: intl.formatMessage(messages.enableSpellchecking),
169 value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremiumFeature ? false : settings.all.app.enableSpellchecking, 167 value: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : settings.all.app.enableSpellchecking,
170 default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremiumFeature ? false : DEFAULT_APP_SETTINGS.enableSpellchecking, 168 default: !this.props.stores.user.data.isPremium && spellcheckerConfig.isPremium ? false : DEFAULT_APP_SETTINGS.enableSpellchecking,
171 }, 169 },
172 spellcheckerLanguage: { 170 spellcheckerLanguage: {
173 label: intl.formatMessage(messages.spellcheckerLanguage), 171 label: intl.formatMessage(globalMessages.spellcheckerLanguage),
174 value: settings.all.app.spellcheckerLanguage, 172 value: settings.all.app.spellcheckerLanguage,
175 options: spellcheckingLanguages, 173 options: spellcheckingLanguages,
176 default: DEFAULT_APP_SETTINGS.spellcheckerLanguage, 174 default: DEFAULT_APP_SETTINGS.spellcheckerLanguage,
@@ -230,7 +228,7 @@ export default @inject('stores', 'actions') @observer class EditSettingsScreen e
230 cacheSize={cacheSize} 228 cacheSize={cacheSize}
231 isClearingAllCache={isClearingAllCache} 229 isClearingAllCache={isClearingAllCache}
232 onClearAllCache={clearAllCache} 230 onClearAllCache={clearAllCache}
233 isSpellcheckerPremiumFeature={spellcheckerConfig.isPremiumFeature} 231 isSpellcheckerPremiumFeature={spellcheckerConfig.isPremium}
234 /> 232 />
235 </ErrorBoundary> 233 </ErrorBoundary>
236 ); 234 );
diff --git a/src/features/spellchecker/index.js b/src/features/spellchecker/index.js
index 63506103c..94883ad17 100644
--- a/src/features/spellchecker/index.js
+++ b/src/features/spellchecker/index.js
@@ -5,7 +5,7 @@ import { DEFAULT_FEATURES_CONFIG } from '../../config';
5const debug = require('debug')('Franz:feature:spellchecker'); 5const debug = require('debug')('Franz:feature:spellchecker');
6 6
7export const config = observable({ 7export const config = observable({
8 isPremiumFeature: DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature, 8 isPremium: DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature,
9}); 9});
10 10
11export default function init(stores) { 11export default function init(stores) {
@@ -14,9 +14,11 @@ export default function init(stores) {
14 autorun(() => { 14 autorun(() => {
15 const { isSpellcheckerPremiumFeature } = stores.features.features; 15 const { isSpellcheckerPremiumFeature } = stores.features.features;
16 16
17 config.isPremiumFeature = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature; 17 console.log('isSpellcheckerPremiumFeature', isSpellcheckerPremiumFeature);
18 18
19 if (!stores.user.data.isPremium && config.isPremiumFeature && stores.settings.app.enableSpellchecking) { 19 config.isPremium = isSpellcheckerPremiumFeature !== undefined ? isSpellcheckerPremiumFeature : DEFAULT_FEATURES_CONFIG.isSpellcheckerPremiumFeature;
20
21 if (!stores.user.data.isPremium && config.isPremium && stores.settings.app.enableSpellchecking) {
20 debug('Override settings.spellcheckerEnabled flag to false'); 22 debug('Override settings.spellcheckerEnabled flag to false');
21 23
22 Object.assign(stores.settings.app, { 24 Object.assign(stores.settings.app, {
diff --git a/src/helpers/i18n-helpers.js b/src/helpers/i18n-helpers.js
index 091b86b06..84146dd8c 100644
--- a/src/helpers/i18n-helpers.js
+++ b/src/helpers/i18n-helpers.js
@@ -28,22 +28,33 @@ export function getLocale({
28 return localeStr; 28 return localeStr;
29} 29}
30 30
31export function getSelectOptions({ locales, resetToDefaultText = '' }) { 31export function getSelectOptions({ locales, resetToDefaultText = '', automaticDetectionText = '' }) {
32 let options = []; 32 const options = [];
33 33
34 if (resetToDefaultText) { 34 if (resetToDefaultText) {
35 options = [ 35 options.push(
36 { 36 {
37 value: '', 37 value: '',
38 label: resetToDefaultText, 38 label: resetToDefaultText,
39 }, {
40 value: '───',
41 label: '───',
42 disabled: true,
43 }, 39 },
44 ]; 40 );
45 } 41 }
46 42
43 if (automaticDetectionText) {
44 options.push(
45 {
46 value: 'automatic',
47 label: automaticDetectionText,
48 },
49 );
50 }
51
52 options.push({
53 value: '───',
54 label: '───',
55 disabled: true,
56 });
57
47 Object.keys(locales).sort(Intl.Collator().compare).forEach((key) => { 58 Object.keys(locales).sort(Intl.Collator().compare).forEach((key) => {
48 options.push({ 59 options.push({
49 value: key, 60 value: key,
diff --git a/src/i18n/globalMessages.js b/src/i18n/globalMessages.js
index 2c724ff6f..7b1618602 100644
--- a/src/i18n/globalMessages.js
+++ b/src/i18n/globalMessages.js
@@ -13,4 +13,20 @@ export default defineMessages({
13 id: 'global.notConnectedToTheInternet', 13 id: 'global.notConnectedToTheInternet',
14 defaultMessage: '!!!You are not connected to the internet.', 14 defaultMessage: '!!!You are not connected to the internet.',
15 }, 15 },
16 spellcheckerLanguage: {
17 id: 'global.spellchecking.language',
18 defaultMessage: '!!!Spell checking language',
19 },
20 spellcheckerSystemDefault: {
21 id: 'global.spellchecker.useDefault',
22 defaultMessage: '!!!Use System Default ({default})',
23 },
24 spellcheckerAutomaticDetection: {
25 id: 'global.spellchecking.autodetect',
26 defaultMessage: '!!!Detect language automatically',
27 },
28 spellcheckerAutomaticDetectionShort: {
29 id: 'global.spellchecking.autodetect.short',
30 defaultMessage: '!!!Automatic',
31 },
16}); 32});
diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json
index 99df6a0ca..4e0c5575d 100644
--- a/src/i18n/locales/en-US.json
+++ b/src/i18n/locales/en-US.json
@@ -1,6 +1,10 @@
1{ 1{
2 "global.api.unhealthy": "Can't connect to Franz online services", 2 "global.api.unhealthy": "Can't connect to Franz online services",
3 "global.notConnectedToTheInternet": "You are not connected to the internet.", 3 "global.notConnectedToTheInternet": "You are not connected to the internet.",
4 "global.spellchecking.language": "Spell checking language",
5 "global.spellchecker.useDefault": "Use System Default ({default})",
6 "global.spellchecking.autodetect": "Detect language automatically",
7 "global.spellchecking.autodetect.short": "Automatic",
4 "welcome.signupButton": "Create a free account", 8 "welcome.signupButton": "Create a free account",
5 "welcome.loginButton": "Login to your account", 9 "welcome.loginButton": "Login to your account",
6 "welcome.slogan": "Messaging that works for you", 10 "welcome.slogan": "Messaging that works for you",
diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js
index a76c03e5a..afb1d8912 100644
--- a/src/webview/contextMenu.js
+++ b/src/webview/contextMenu.js
@@ -207,8 +207,6 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
207 }); 207 });
208 }); 208 });
209 209
210 console.log('isSpellcheckEnabled', isSpellcheckEnabled);
211
212 menuTpl.push({ 210 menuTpl.push({
213 type: 'separator', 211 type: 'separator',
214 }, { 212 }, {
@@ -234,6 +232,16 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck
234 }, 232 },
235 }, 233 },
236 { 234 {
235 id: 'automaticDetection',
236 label: 'Automatic language detection',
237 type: 'radio',
238 checked: spellcheckerLanguage === 'automatic',
239 click() {
240 debug('Detect language automatically');
241 ipcRenderer.sendToHost('set-service-spellchecker-language', 'automatic');
242 },
243 },
244 {
237 type: 'separator', 245 type: 'separator',
238 visible: defaultSpellcheckerLanguage !== spellcheckerLanguage, 246 visible: defaultSpellcheckerLanguage !== spellcheckerLanguage,
239 }, 247 },
diff --git a/src/webview/recipe.js b/src/webview/recipe.js
index c718b348e..1e5d74b1f 100644
--- a/src/webview/recipe.js
+++ b/src/webview/recipe.js
@@ -1,10 +1,12 @@
1import { ipcRenderer } from 'electron'; 1import { ipcRenderer } from 'electron';
2import path from 'path'; 2import path from 'path';
3import { autorun, computed, observable } from 'mobx'; 3import { autorun, computed, observable } from 'mobx';
4import { loadModule } from 'cld3-asm';
5import { debounce } from 'lodash';
4 6
5import RecipeWebview from './lib/RecipeWebview'; 7import RecipeWebview from './lib/RecipeWebview';
6 8
7import spellchecker, { switchDict, disable as disableSpellchecker } from './spellchecker'; 9import spellchecker, { switchDict, disable as disableSpellchecker, getSpellcheckerLocaleByFuzzyIdentifier } from './spellchecker';
8import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode'; 10import { injectDarkModeStyle, isDarkModeStyleInjected, removeDarkModeStyle } from './darkmode';
9import contextMenu from './contextMenu'; 11import contextMenu from './contextMenu';
10import './notifications'; 12import './notifications';
@@ -40,6 +42,8 @@ class RecipeController {
40 return this.settings.service.spellcheckerLanguage || this.settings.app.spellcheckerLanguage; 42 return this.settings.service.spellcheckerLanguage || this.settings.app.spellcheckerLanguage;
41 } 43 }
42 44
45 cldIdentifier = null;
46
43 async initialize() { 47 async initialize() {
44 Object.keys(this.ipcEvents).forEach((channel) => { 48 Object.keys(this.ipcEvents).forEach((channel) => {
45 ipcRenderer.on(channel, (...args) => { 49 ipcRenderer.on(channel, (...args) => {
@@ -87,10 +91,22 @@ class RecipeController {
87 91
88 if (this.settings.app.enableSpellchecking) { 92 if (this.settings.app.enableSpellchecking) {
89 debug('Setting spellchecker language to', this.spellcheckerLanguage); 93 debug('Setting spellchecker language to', this.spellcheckerLanguage);
90 switchDict(this.spellcheckerLanguage); 94 let { spellcheckerLanguage } = this;
95 if (spellcheckerLanguage === 'automatic') {
96 this.automaticLanguageDetection();
97 debug('Found `automatic` locale, falling back to user locale until detected', this.settings.app.locale);
98 spellcheckerLanguage = this.settings.app.locale;
99 } else if (this.cldIdentifier) {
100 this.cldIdentifier.destroy();
101 }
102 switchDict(spellcheckerLanguage);
91 } else { 103 } else {
92 debug('Disable spellchecker'); 104 debug('Disable spellchecker');
93 disableSpellchecker(); 105 disableSpellchecker();
106
107 if (this.cldIdentifier) {
108 this.cldIdentifier.destroy();
109 }
94 } 110 }
95 111
96 if (this.settings.service.isDarkModeEnabled) { 112 if (this.settings.service.isDarkModeEnabled) {
@@ -113,6 +129,42 @@ class RecipeController {
113 serviceIdEcho(event) { 129 serviceIdEcho(event) {
114 event.sender.send('service-id', this.settings.service.id); 130 event.sender.send('service-id', this.settings.service.id);
115 } 131 }
132
133 async automaticLanguageDetection() {
134 const cldFactory = await loadModule();
135 this.cldIdentifier = cldFactory.create(0, 1000);
136
137 window.addEventListener('keyup', debounce((e) => {
138 const element = e.target;
139
140 console.log(element);
141
142 if (!element) return;
143
144 let value = '';
145 if (element.isContentEditable) {
146 value = element.textContent;
147 } else if (element.value) {
148 value = element.value;
149 }
150
151 // Force a minimum length to get better detection results
152 if (value.length < 30) return;
153
154 debug('Detecting language for', value);
155 const findResult = this.cldIdentifier.findLanguage(value);
156
157 debug('Language detection result', findResult);
158
159 if (findResult.is_reliable) {
160 const spellcheckerLocale = getSpellcheckerLocaleByFuzzyIdentifier(findResult.language);
161 debug('Language detected reliably, setting spellchecker language to', spellcheckerLocale);
162 if (spellcheckerLocale) {
163 switchDict(spellcheckerLocale);
164 }
165 }
166 }, 225));
167 }
116} 168}
117 169
118/* eslint-disable no-new */ 170/* eslint-disable no-new */
diff --git a/src/webview/spellchecker.js b/src/webview/spellchecker.js
index becaed449..9158b3b94 100644
--- a/src/webview/spellchecker.js
+++ b/src/webview/spellchecker.js
@@ -3,6 +3,7 @@ import { SpellCheckerProvider } from 'electron-hunspell';
3import path from 'path'; 3import path from 'path';
4 4
5import { DICTIONARY_PATH } from '../config'; 5import { DICTIONARY_PATH } from '../config';
6import { SPELLCHECKER_LOCALES } from '../i18n/languages';
6 7
7const debug = require('debug')('Franz:spellchecker'); 8const debug = require('debug')('Franz:spellchecker');
8 9
@@ -82,3 +83,13 @@ export function disable() {
82 currentDict = null; 83 currentDict = null;
83 } 84 }
84} 85}
86
87export function getSpellcheckerLocaleByFuzzyIdentifier(identifier) {
88 const locales = Object.keys(SPELLCHECKER_LOCALES).filter(key => key === identifier.toLowerCase() || key.split('-')[0] === identifier.toLowerCase());
89
90 if (locales.length >= 1) {
91 return locales[0];
92 }
93
94 return null;
95}