1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-01-14 00:29:38 +02:00

Compare commits

..

25 Commits

Author SHA1 Message Date
Laurent Cozic
c0ceefab8a Restrict auto-detection of links and option to toggle linkify 2020-12-09 00:58:36 +00:00
Laurent Cozic
46ed1304f2 Desktop: Improved warning banner colors 2020-12-08 23:44:54 +00:00
Laurent Cozic
01cf0de974 Desktop: Fixed title input field width on small windows 2020-12-08 23:27:11 +00:00
Laurent Cozic
abf5d16da9 Doc: Fixed master key encryption method link 2020-12-08 22:02:17 +00:00
Laurent Cozic
f21199a7f3 Chore: Convert test-utils to TypeScript 2020-12-08 20:01:33 +00:00
Laurent Cozic
cdf2873883 Plugins: Commands would not show up in keymap editor when no shortcut was associated with them
Ref: https://discourse.joplinapp.org/t/plugin-note-tabs/12752/39
2020-12-08 19:45:08 +00:00
Laurent Cozic
0390928fea Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-12-08 19:04:03 +00:00
Laurent Cozic
efb3546675 Plugins: Add support for workspace.onSyncStart event 2020-12-08 19:03:22 +00:00
Ji-Hyeon Gim
169841dcc4 All: Translation: Update ko.po (#4200)
It updates fuzzy translations for Korean.

Signed-off-by: Ji-Hyeon Gim <potatogim@potatogim.net>
2020-12-07 11:49:22 -05:00
Helmut K. C. Tessarek
b780261153 Chore: moving the keycode map to a separate file (#4192)
/ref https://github.com/laurent22/joplin/pull/4022#issuecomment-726263640
2020-12-06 15:01:30 +00:00
Zhang YANG
c906354510 All: Translation: Update zh_CN (#4195) 2020-12-05 20:44:02 -05:00
Helmut K. C. Tessarek
6487fde09d update: en_US.po 2020-12-05 19:33:58 -05:00
Helmut K. C. Tessarek
50f046ffc4 Update translations 2020-12-05 16:36:47 -05:00
Helmut K. C. Tessarek
ded14ff8db move fi_FI.po to the correct path 2020-12-05 16:34:37 -05:00
Laurent Cozic
64bbd93f54 Tools: Skip electronRebuild in postinstall to make boostrap faster, but add it to dist script 2020-12-05 12:40:14 +00:00
Laurent Cozic
9a30b69610 Doc: Added comment about stapling macOS app 2020-12-05 12:18:31 +00:00
Laurent Cozic
046433a947 Tools: Fixed issue with gettext not knowing how to parse regex that includes backtick 2020-12-05 11:54:58 +00:00
Laurent Cozic
42232fac84 Desktop release v1.5.4 2020-12-05 11:06:54 +00:00
Laurent Cozic
245976f659 Chore: trying to fix notarization 2020-12-05 11:06:20 +00:00
Laurent Cozic
8d90cc234f Clipper: Fixes #4105: Handle certain types of code block 2020-12-02 15:43:44 +00:00
Manuel Tassi
5183767e43 Update it_IT.po (#4169) 2020-12-02 10:47:42 +00:00
Alexander Fischer
ceb625dbeb updated german translations (#4168) 2020-12-02 10:47:11 +00:00
mrkaato
7677d9cd7d Add Finnish translation (#4156) 2020-12-02 10:44:36 +00:00
Caleb John
92fe5e2362 Desktop: Fixes #4036: Focus editor after pressing toolbar buttons (#4037) 2020-12-02 10:36:00 +00:00
Laurent Cozic
717b8da1f8 Tools: Cleaned up tests and splitted sync tests into smaller parts 2020-12-01 18:05:24 +00:00
175 changed files with 99618 additions and 84605 deletions

View File

@@ -10,6 +10,8 @@ highlight.pack.js
Modules/TinyMCE/IconPack/postinstall.js
Modules/TinyMCE/JoplinLists/
Modules/TinyMCE/langs/
packages/turndown/
packages/turndown-plugin-gfm/
node_modules/
packages/lib/lib/lib.js
packages/lib/locales/index.js
@@ -104,6 +106,9 @@ packages/app-cli/tests/models_Note.js.map
packages/app-cli/tests/models_Setting.d.ts
packages/app-cli/tests/models_Setting.js
packages/app-cli/tests/models_Setting.js.map
packages/app-cli/tests/services/plugins/api/JoplinViewMenuItem.d.ts
packages/app-cli/tests/services/plugins/api/JoplinViewMenuItem.js
packages/app-cli/tests/services/plugins/api/JoplinViewMenuItem.js.map
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.d.ts
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js.map
@@ -263,6 +268,9 @@ packages/app-cli/tests/synchronizer_MigrationHandler.js.map
packages/app-cli/tests/test-utils-synchronizer.d.ts
packages/app-cli/tests/test-utils-synchronizer.js
packages/app-cli/tests/test-utils-synchronizer.js.map
packages/app-cli/tests/test-utils.d.ts
packages/app-cli/tests/test-utils.js
packages/app-cli/tests/test-utils.js.map
packages/app-desktop/ElectronAppWrapper.d.ts
packages/app-desktop/ElectronAppWrapper.js
packages/app-desktop/ElectronAppWrapper.js.map
@@ -959,6 +967,12 @@ packages/lib/services/ExternalEditWatcher.js.map
packages/lib/services/KeymapService.d.ts
packages/lib/services/KeymapService.js
packages/lib/services/KeymapService.js.map
packages/lib/services/KeymapService_keycodeToElectronMap.d.ts
packages/lib/services/KeymapService_keycodeToElectronMap.js
packages/lib/services/KeymapService_keycodeToElectronMap.js.map
packages/lib/services/KeymapService_keysRegExp.d.ts
packages/lib/services/KeymapService_keysRegExp.js
packages/lib/services/KeymapService_keysRegExp.js.map
packages/lib/services/KvStore.d.ts
packages/lib/services/KvStore.js
packages/lib/services/KvStore.js.map

View File

@@ -24,6 +24,7 @@ module.exports = {
'afterAll': 'readonly',
'beforeEach': 'readonly',
'afterEach': 'readonly',
'jest': 'readonly',
// React Native variables
'__DEV__': 'readonly',

14
.gitignore vendored
View File

@@ -95,6 +95,9 @@ packages/app-cli/tests/models_Note.js.map
packages/app-cli/tests/models_Setting.d.ts
packages/app-cli/tests/models_Setting.js
packages/app-cli/tests/models_Setting.js.map
packages/app-cli/tests/services/plugins/api/JoplinViewMenuItem.d.ts
packages/app-cli/tests/services/plugins/api/JoplinViewMenuItem.js
packages/app-cli/tests/services/plugins/api/JoplinViewMenuItem.js.map
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.d.ts
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js
packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js.map
@@ -254,6 +257,9 @@ packages/app-cli/tests/synchronizer_MigrationHandler.js.map
packages/app-cli/tests/test-utils-synchronizer.d.ts
packages/app-cli/tests/test-utils-synchronizer.js
packages/app-cli/tests/test-utils-synchronizer.js.map
packages/app-cli/tests/test-utils.d.ts
packages/app-cli/tests/test-utils.js
packages/app-cli/tests/test-utils.js.map
packages/app-desktop/ElectronAppWrapper.d.ts
packages/app-desktop/ElectronAppWrapper.js
packages/app-desktop/ElectronAppWrapper.js.map
@@ -950,6 +956,12 @@ packages/lib/services/ExternalEditWatcher.js.map
packages/lib/services/KeymapService.d.ts
packages/lib/services/KeymapService.js
packages/lib/services/KeymapService.js.map
packages/lib/services/KeymapService_keycodeToElectronMap.d.ts
packages/lib/services/KeymapService_keycodeToElectronMap.js
packages/lib/services/KeymapService_keycodeToElectronMap.js.map
packages/lib/services/KeymapService_keysRegExp.d.ts
packages/lib/services/KeymapService_keysRegExp.js
packages/lib/services/KeymapService_keysRegExp.js.map
packages/lib/services/KvStore.d.ts
packages/lib/services/KvStore.js
packages/lib/services/KvStore.js.map
@@ -1349,4 +1361,4 @@ packages/renderer/pathUtils.js.map
packages/renderer/utils.d.ts
packages/renderer/utils.js
packages/renderer/utils.js.map
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD

View File

@@ -435,44 +435,45 @@ Current translations:
<!-- LOCALE-TABLE-AUTO-GENERATED -->
&nbsp; | Language | Po File | Last translator | Percent done
---|---|---|---|---
![](https://joplinapp.org/images/flags/country-4x3/arableague.png) | Arabic | [ar](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/ar.po) | [أحمد باشا إبراهيم](mailto:fi_ahmed_bacha@esi.dz) | 78%
![](https://joplinapp.org/images/flags/es/basque_country.png) | Basque | [eu](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/eu.po) | juan.abasolo@ehu.eus | 33%
![](https://joplinapp.org/images/flags/country-4x3/ba.png) | Bosnian | [bs_BA](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/bs_BA.po) | [Derviš T.](mailto:dervis.t@pm.me) | 82%
![](https://joplinapp.org/images/flags/country-4x3/bg.png) | Bulgarian | [bg_BG](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/bg_BG.po) | | 65%
![](https://joplinapp.org/images/flags/es/catalonia.png) | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/ca.po) | jmontane, 2019 | 95%
![](https://joplinapp.org/images/flags/country-4x3/hr.png) | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/hr_HR.po) | [Hrvoje Mandić](mailto:trbuhom@net.hr) | 27%
![](https://joplinapp.org/images/flags/country-4x3/cz.png) | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/cs_CZ.po) | [Lukas Helebrandt](mailto:lukas@aiya.cz) | 98%
![](https://joplinapp.org/images/flags/country-4x3/dk.png) | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/da_DK.po) | [Morten Juhl-Johansen Zölde-Fejér](mailto:mjjzf@syntaktisk.) | 72%
![](https://joplinapp.org/images/flags/country-4x3/de.png) | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/de_DE.po) | [Ettore Atalan](mailto:atalanttore@users.noreply.github.com) | 97%
![](https://joplinapp.org/images/flags/country-4x3/ee.png) | Eesti Keel | [et_EE](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/et_EE.po) | | 65%
![](https://joplinapp.org/images/flags/country-4x3/gb.png) | English (UK) | [en_GB](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/en_GB.po) | | 100%
![](https://joplinapp.org/images/flags/country-4x3/us.png) | English (US) | [en_US](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/en_US.po) | | 100%
![](https://joplinapp.org/images/flags/country-4x3/es.png) | Español | [es_ES](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/es_ES.po) | [Mario Campo](mailto:mario.campo@gmail.com) | 98%
![](https://joplinapp.org/images/flags/esperanto.png) | Esperanto | [eo](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/eo.po) | Marton Paulo | 37%
![](https://joplinapp.org/images/flags/country-4x3/fr.png) | Français | [fr_FR](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/fr_FR.po) | Laurent Cozic | 98%
![](https://joplinapp.org/images/flags/es/galicia.png) | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/gl_ES.po) | [Marcos Lans](mailto:marcoslansgarza@gmail.com) | 42%
![](https://joplinapp.org/images/flags/country-4x3/id.png) | Indonesian | [id_ID](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/id_ID.po) | [Fathy AR](mailto:16875937+fathyar@users.noreply.github.com) | 92%
![](https://joplinapp.org/images/flags/country-4x3/it.png) | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/it_IT.po) | [Alessandro Bernardello](mailto:mailfilledwithspam@gmail.com) | 98%
![](https://joplinapp.org/images/flags/country-4x3/nl.png) | Nederlands | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/nl_NL.po) | [MetBril](mailto:metbril@users.noreply.github.com) | 94%
![](https://joplinapp.org/images/flags/country-4x3/be.png) | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/nl_BE.po) | | 33%
![](https://joplinapp.org/images/flags/country-4x3/no.png) | Norwegian | [nb_NO](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/nb_NO.po) | [Mats Estensen](mailto:code@mxe.no) | 87%
![](https://joplinapp.org/images/flags/country-4x3/ir.png) | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 82%
![](https://joplinapp.org/images/flags/country-4x3/pl.png) | Polski | [pl_PL](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/pl_PL.po) | | 97%
![](https://joplinapp.org/images/flags/country-4x3/pt.png) | Português | [pt_PT](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/pt_PT.po) | [João Duarte](mailto:jduar@protonmail.com) | 98%
![](https://joplinapp.org/images/flags/country-4x3/br.png) | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/pt_BR.po) | [Renato Nunes Bastos](mailto:rnbastos@gmail.com) | 96%
![](https://joplinapp.org/images/flags/country-4x3/ro.png) | Română | [ro](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/ro.po) | [Cristi Duluta](mailto:cristi.duluta@gmail.com) | 77%
![](https://joplinapp.org/images/flags/country-4x3/si.png) | Slovenian | [sl_SI](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/sl_SI.po) | | 41%
![](https://joplinapp.org/images/flags/country-4x3/se.png) | Svenska | [sv](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/sv.po) | [Jonatan Nyberg](mailto:jonatan@autistici.org) | 70%
![](https://joplinapp.org/images/flags/country-4x3/th.png) | Thai | [th_TH](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/th_TH.po) | | 52%
![](https://joplinapp.org/images/flags/country-4x3/vi.png) | Tiếng Việt | [vi](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/vi.po) | | 84%
![](https://joplinapp.org/images/flags/country-4x3/tr.png) | Türkçe | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 97%
![](https://joplinapp.org/images/flags/country-4x3/gr.png) | Ελληνικά | [el_GR](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/el_GR.po) | [Harris Arvanitis](mailto:xaris@tuta.io) | 95%
![](https://joplinapp.org/images/flags/country-4x3/ru.png) | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/ru_RU.po) | [Sergey Segeda](mailto:thesermanarm@gmail.com) | 94%
![](https://joplinapp.org/images/flags/country-4x3/rs.png) | српски језик | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/sr_RS.po) | | 70%
![](https://joplinapp.org/images/flags/country-4x3/cn.png) | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/zh_CN.po) | [WhiredPlanck](mailto:fungdaat31@outlook.com) | 95%
![](https://joplinapp.org/images/flags/country-4x3/tw.png) | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/zh_TW.po) | [Yaoze Ye](mailto:yaozeye@yahoo.co.jp) | 94%
![](https://joplinapp.org/images/flags/country-4x3/jp.png) | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/ja_JP.po) | [genneko](mailto:genneko217@gmail.com) | 99%
![](https://joplinapp.org/images/flags/country-4x3/kr.png) | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/app-cli/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 99%
![](https://joplinapp.org/images/flags/country-4x3/arableague.png) | Arabic | [ar](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ar.po) | [أحمد باشا إبراهيم](mailto:fi_ahmed_bacha@esi.dz) | 77%
![](https://joplinapp.org/images/flags/es/basque_country.png) | Basque | [eu](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/eu.po) | juan.abasolo@ehu.eus | 33%
![](https://joplinapp.org/images/flags/country-4x3/ba.png) | Bosnian (Bosna i Hercegovina) | [bs_BA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bs_BA.po) | [Derviš T.](mailto:dervis.t@pm.me) | 79%
![](https://joplinapp.org/images/flags/country-4x3/bg.png) | Bulgarian (България) | [bg_BG](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bg_BG.po) | | 64%
![](https://joplinapp.org/images/flags/es/catalonia.png) | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ca.po) | jmontane, 2019 | 92%
![](https://joplinapp.org/images/flags/country-4x3/hr.png) | Croatian (Hrvatska) | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hr_HR.po) | [Hrvoje Mandić](mailto:trbuhom@net.hr) | 26%
![](https://joplinapp.org/images/flags/country-4x3/cz.png) | Czech (Česká republika) | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/cs_CZ.po) | [Lukas Helebrandt](mailto:lukas@aiya.cz) | 96%
![](https://joplinapp.org/images/flags/country-4x3/dk.png) | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | Mustafa Al-Dailemi (dailemi@hotmail.com)Language-Team: | 79%
![](https://joplinapp.org/images/flags/country-4x3/de.png) | Deutsch (Deutschland) | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/de_DE.po) | [Ettore Atalan](mailto:atalanttore@users.noreply.github.com) | 96%
![](https://joplinapp.org/images/flags/country-4x3/ee.png) | Eesti Keel (Eesti) | [et_EE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/et_EE.po) | | 63%
![](https://joplinapp.org/images/flags/country-4x3/gb.png) | English (United Kingdom) | [en_GB](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_GB.po) | | 100%
![](https://joplinapp.org/images/flags/country-4x3/us.png) | English (United States of America) | [en_US](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_US.po) | | 100%
![](https://joplinapp.org/images/flags/country-4x3/es.png) | Español (España) | [es_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/es_ES.po) | [Mario Campo](mailto:mario.campo@gmail.com) | 96%
![](https://joplinapp.org/images/flags/esperanto.png) | Esperanto | [eo](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/eo.po) | Marton Paulo | 36%
![](https://joplinapp.org/images/flags/country-4x3/fi.png) | Finnish (Suomi) | [fi_FI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fi_FI.po) | | 97%
![](https://joplinapp.org/images/flags/country-4x3/fr.png) | Français (France) | [fr_FR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fr_FR.po) | Laurent Cozic | 96%
![](https://joplinapp.org/images/flags/es/galicia.png) | Galician (España) | [gl_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/gl_ES.po) | [Marcos Lans](mailto:marcoslansgarza@gmail.com) | 42%
![](https://joplinapp.org/images/flags/country-4x3/id.png) | Indonesian (Indonesia) | [id_ID](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/id_ID.po) | [Fathy AR](mailto:16875937+fathyar@users.noreply.github.com) | 88%
![](https://joplinapp.org/images/flags/country-4x3/it.png) | Italiano (Italia) | [it_IT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/it_IT.po) | [Alessandro Bernardello](mailto:mailfilledwithspam@gmail.com) | 97%
![](https://joplinapp.org/images/flags/country-4x3/be.png) | Nederlands (België, Belgique, Belgien) | [nl_BE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_BE.po) | | 33%
![](https://joplinapp.org/images/flags/country-4x3/nl.png) | Nederlands (Nederland) | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_NL.po) | [MetBril](mailto:metbril@users.noreply.github.com) | 96%
![](https://joplinapp.org/images/flags/country-4x3/no.png) | Norwegian (Norge, Noreg) | [nb_NO](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nb_NO.po) | [Mats Estensen](mailto:code@mxe.no) | 85%
![](https://joplinapp.org/images/flags/country-4x3/ir.png) | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 79%
![](https://joplinapp.org/images/flags/country-4x3/pl.png) | Polski (Polska) | [pl_PL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pl_PL.po) | | 95%
![](https://joplinapp.org/images/flags/country-4x3/br.png) | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_BR.po) | [Renato Nunes Bastos](mailto:rnbastos@gmail.com) | 93%
![](https://joplinapp.org/images/flags/country-4x3/pt.png) | Português (Portugal) | [pt_PT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pt_PT.po) | [João Duarte](mailto:jduar@protonmail.com) | 95%
![](https://joplinapp.org/images/flags/country-4x3/ro.png) | Română | [ro](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ro.po) | [Cristi Duluta](mailto:cristi.duluta@gmail.com) | 74%
![](https://joplinapp.org/images/flags/country-4x3/si.png) | Slovenian (Slovenija) | [sl_SI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sl_SI.po) | | 41%
![](https://joplinapp.org/images/flags/country-4x3/se.png) | Svenska | [sv](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sv.po) | [Jonatan Nyberg](mailto:jonatan@autistici.org) | 68%
![](https://joplinapp.org/images/flags/country-4x3/th.png) | Thai (ประเทศไทย) | [th_TH](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/th_TH.po) | | 50%
![](https://joplinapp.org/images/flags/country-4x3/vi.png) | Tiếng Việt | [vi](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/vi.po) | | 82%
![](https://joplinapp.org/images/flags/country-4x3/tr.png) | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 94%
![](https://joplinapp.org/images/flags/country-4x3/gr.png) | Ελληνικά (Ελλάδα) | [el_GR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/el_GR.po) | [Harris Arvanitis](mailto:xaris@tuta.io) | 92%
![](https://joplinapp.org/images/flags/country-4x3/ru.png) | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Sergey Segeda](mailto:thesermanarm@gmail.com) | 92%
![](https://joplinapp.org/images/flags/country-4x3/rs.png) | српски језик (Србија) | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sr_RS.po) | | 69%
![](https://joplinapp.org/images/flags/country-4x3/cn.png) | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_CN.po) | [WhiredPlanck](mailto:fungdaat31@outlook.com) | 97%
![](https://joplinapp.org/images/flags/country-4x3/tw.png) | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Yaoze Ye](mailto:yaozeye@yahoo.co.jp) | 91%
![](https://joplinapp.org/images/flags/country-4x3/jp.png) | 日本語 (日本) | [ja_JP](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ja_JP.po) | [genneko](mailto:genneko217@gmail.com) | 97%
![](https://joplinapp.org/images/flags/country-4x3/kr.png) | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 97%
<!-- LOCALE-TABLE-AUTO-GENERATED -->
# Contributors

View File

@@ -17,6 +17,7 @@
"buildDoc": "./packages/tools/build-all.sh",
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out docs/api/references/plugin_api packages/lib/services/plugins/api/",
"buildTranslations": "npm run tsc && node packages/tools/build-translation.js",
"buildTranslationsNoTsc": "node packages/tools/build-translation.js",
"buildWebsite": "npm run buildApiDoc && node ./packages/tools/build-website.js && npm run buildPluginDoc",
"clean": "lerna clean -y && lerna run clean",
"generateDatabaseTypes": "node packages/tools/generate-database-types",

View File

@@ -32,7 +32,7 @@ describe('HtmlToMd', function() {
const htmlPath = `${basePath}/${htmlFilename}`;
const mdPath = `${basePath}/${filename(htmlFilename)}.md`;
// if (htmlFilename !== 'joplin_source_2.html') continue;
// if (htmlFilename !== 'code_3.html') continue;
// if (htmlFilename.indexOf('image_preserve_size') !== 0) continue;
@@ -61,16 +61,30 @@ describe('HtmlToMd', function() {
}
if (actualMd !== expectedMd) {
console.info('');
console.info(`Error converting file: ${htmlFilename}`);
console.info('--------------------------------- Got:');
console.info(actualMd);
console.info('--------------------------------- Raw:');
console.info(actualMd.split('\n'));
console.info('--------------------------------- Expected:');
console.info(expectedMd.split('\n'));
console.info('--------------------------------------------');
console.info('');
const result = [];
result.push('');
result.push(`Error converting file: ${htmlFilename}`);
result.push('--------------------------------- Got:');
result.push(actualMd.split('\n').map(l => `"${l}"`).join('\n'));
result.push('--------------------------------- Expected:');
result.push(expectedMd.split('\n').map(l => `"${l}"`).join('\n'));
result.push('--------------------------------------------');
result.push('');
console.info(result.join('\n'));
// console.info('');
// console.info(`Error converting file: ${htmlFilename}`);
// console.info('--------------------------------- Got:');
// console.info(actualMd);
// console.info('--------------------------------- Raw:');
// console.info(actualMd.split('\n'));
// console.info('--------------------------------- Expected:');
// console.info(expectedMd.split('\n'));
// console.info('--------------------------------------------');
// console.info('');
expect(false).toBe(true);
// return;

View File

@@ -395,4 +395,4 @@ describe('Synchronizer.basics', function() {
expect((await Note.all()).length).toBe(11);
}));
});
});

View File

@@ -291,4 +291,4 @@ describe('Synchronizer.conflicts', function() {
await ignorableNoteConflictTest(true);
}));
});
});

View File

@@ -400,4 +400,4 @@ describe('Synchronizer.e2ee', function() {
expect(note1_2.title).toBe('');
}));
});
});

View File

@@ -354,4 +354,4 @@ describe('Synchronizer.resources', function() {
expect(syncItems[1].sync_disabled).toBe(1);
}));
});
});

View File

@@ -182,4 +182,4 @@ describe('Synchronizer.revisions', function() {
expect((await Revision.all()).length).toBe(0);
}));
});
});

View File

@@ -0,0 +1 @@
<pre style="font-family: monospace;"><span>├── myproj_app<br>│ ├── api.py<br>│ └── Dockerfile</span></pre>

View File

@@ -0,0 +1,5 @@
```
├── myproj_app
│ ├── api.py
│ └── Dockerfile
```

View File

@@ -0,0 +1,57 @@
import KeymapService from '@joplin/lib/services/KeymapService';
import PluginService from '@joplin/lib/services/plugins/PluginService';
const { newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } = require('../../../test-utils');
describe('JoplinViewMenuItem', () => {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
afterEach(async () => {
await afterEachCleanUp();
});
test('should register commands with the keymap service', async () => {
const service = new newPluginService() as PluginService;
KeymapService.instance().initialize();
const pluginScript = newPluginScript(`
joplin.plugins.register({
onStart: async function() {
await joplin.commands.register({
name: 'testCommand1',
label: 'My Test Command 1',
iconName: 'fas fa-music',
execute: async () => {},
});
await joplin.views.menuItems.create('myMenuItem1', 'testCommand1', 'tools', { accelerator: 'CmdOrCtrl+Alt+Shift+B' });
await joplin.commands.register({
name: 'testCommand2',
label: 'My Test Command 2',
iconName: 'fas fa-music',
execute: async () => {},
});
await joplin.views.menuItems.create('myMenuItem2', 'testCommand2', 'tools');
},
});
`);
const plugin = await service.loadPluginFromJsBundle('', pluginScript);
await service.runPlugin(plugin);
const commandNames = KeymapService.instance().getCommandNames();
expect(commandNames.includes('testCommand1')).toBe(true);
expect(commandNames.includes('testCommand2')).toBe(true);
await service.destroy();
});
});

View File

@@ -7,8 +7,13 @@ joplin.plugins.register({
console.info('Alarm was triggered for note: ', note);
});
joplin.workspace.onSyncComplete(async () => {
joplin.workspace.onSyncStart(async (event:any) => {
console.info('Sync has started...');
});
joplin.workspace.onSyncComplete(async (event:any) => {
console.info('Sync has completed');
console.info('With errors:', event.withErrors);
});
},
});

View File

@@ -57,7 +57,7 @@ describe('synchronizer_MigrationHandler', function() {
// global Jest timeout. So we need to set it globally.
//
// https://github.com/facebook/jest/issues/5055#issuecomment-513585906
jest.setTimeout(specTimeout)
jest.setTimeout(specTimeout);
// To test the migrations, we have to use the filesystem sync target
// because the sync target snapshots are plain files. Eventually

View File

@@ -62,4 +62,4 @@ export async function localNotesFoldersSameAsRemote(locals: any[], expect: Funct
}
expect(error).toBe(null);
}
}

View File

@@ -1,10 +1,24 @@
/* eslint-disable require-atomic-updates */
import BaseApplication from '@joplin/lib/BaseApplication';
import BaseModel from '@joplin/lib/BaseModel';
import Logger, { TargetType, LoggerWrapper } from '@joplin/lib/Logger';
import Setting from '@joplin/lib/models/Setting';
import BaseService from '@joplin/lib/services/BaseService';
import FsDriverNode from '@joplin/lib/fs-driver-node';
import time from '@joplin/lib/time';
import shim from '@joplin/lib/shim';
import uuid from '@joplin/lib/uuid';
import ResourceService from '@joplin/lib/services/ResourceService';
import KeymapService from '@joplin/lib/services/KeymapService';
import KvStore from '@joplin/lib/services/KvStore';
import KeychainServiceDriver from '@joplin/lib/services/keychain/KeychainServiceDriver.node';
import KeychainServiceDriverDummy from '@joplin/lib/services/keychain/KeychainServiceDriver.dummy';
import PluginRunner from '../app/services/plugins/PluginRunner';
import PluginService from '@joplin/lib/services/plugins/PluginService';
const fs = require('fs-extra');
const { JoplinDatabase } = require('@joplin/lib/joplin-database.js');
const { DatabaseDriverNode } = require('@joplin/lib/database-driver-node.js');
const BaseApplication = require('@joplin/lib/BaseApplication').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const Folder = require('@joplin/lib/models/Folder.js');
const Note = require('@joplin/lib/models/Note.js');
const ItemChange = require('@joplin/lib/models/ItemChange.js');
@@ -12,8 +26,6 @@ const Resource = require('@joplin/lib/models/Resource.js');
const Tag = require('@joplin/lib/models/Tag.js');
const NoteTag = require('@joplin/lib/models/NoteTag.js');
const Revision = require('@joplin/lib/models/Revision.js');
const Logger = require('@joplin/lib/Logger').default;
const Setting = require('@joplin/lib/models/Setting').default;
const MasterKey = require('@joplin/lib/models/MasterKey');
const BaseItem = require('@joplin/lib/models/BaseItem.js');
const { FileApi } = require('@joplin/lib/file-api.js');
@@ -23,12 +35,7 @@ const { FileApiDriverWebDav } = require('@joplin/lib/file-api-driver-webdav.js')
const { FileApiDriverDropbox } = require('@joplin/lib/file-api-driver-dropbox.js');
const { FileApiDriverOneDrive } = require('@joplin/lib/file-api-driver-onedrive.js');
const { FileApiDriverAmazonS3 } = require('@joplin/lib/file-api-driver-amazon-s3.js');
const BaseService = require('@joplin/lib/services/BaseService').default;
const FsDriverNode = require('@joplin/lib/fs-driver-node').default;
const time = require('@joplin/lib/time').default;
const { shimInit } = require('@joplin/lib/shim-init-node.js');
const shim = require('@joplin/lib/shim').default;
const uuid = require('@joplin/lib/uuid').default;
const SyncTargetRegistry = require('@joplin/lib/SyncTargetRegistry.js');
const SyncTargetMemory = require('@joplin/lib/SyncTargetMemory.js');
const SyncTargetFilesystem = require('@joplin/lib/SyncTargetFilesystem.js');
@@ -38,20 +45,14 @@ const SyncTargetDropbox = require('@joplin/lib/SyncTargetDropbox.js');
const SyncTargetAmazonS3 = require('@joplin/lib/SyncTargetAmazonS3.js');
const EncryptionService = require('@joplin/lib/services/EncryptionService.js');
const DecryptionWorker = require('@joplin/lib/services/DecryptionWorker.js');
const ResourceService = require('@joplin/lib/services/ResourceService').default;
const RevisionService = require('@joplin/lib/services/RevisionService.js');
const ResourceFetcher = require('@joplin/lib/services/ResourceFetcher.js');
const KvStore = require('@joplin/lib/services/KvStore').default;
const WebDavApi = require('@joplin/lib/WebDavApi');
const DropboxApi = require('@joplin/lib/DropboxApi');
const { OneDriveApi } = require('@joplin/lib/onedrive-api');
const { loadKeychainServiceAndSettings } = require('@joplin/lib/services/SettingUtils');
const KeychainServiceDriver = require('@joplin/lib/services/keychain/KeychainServiceDriver.node').default;
const KeychainServiceDriverDummy = require('@joplin/lib/services/keychain/KeychainServiceDriver.dummy').default;
const md5 = require('md5');
const S3 = require('aws-sdk/clients/s3');
const PluginRunner = require('../app/services/plugins/PluginRunner').default;
const PluginService = require('@joplin/lib/services/plugins/PluginService').default;
const { Dirnames } = require('@joplin/lib/services/synchronizer/utils/types');
const sharp = require('sharp');
@@ -62,16 +63,16 @@ const sharp = require('sharp');
// Jest, to make debugging easier, but it's not clear how to get this info).
const suiteName_ = uuid.createNano();
const databases_ = [];
let synchronizers_ = [];
const synchronizerContexts_ = {};
const fileApis_ = {};
const encryptionServices_ = [];
const revisionServices_ = [];
const decryptionWorkers_ = [];
const resourceServices_ = [];
const resourceFetchers_ = [];
const kvStores_ = [];
const databases_: any[] = [];
let synchronizers_: any[] = [];
const synchronizerContexts_: any = {};
const fileApis_: any = {};
const encryptionServices_: any[] = [];
const revisionServices_: any[] = [];
const decryptionWorkers_: any[] = [];
const resourceServices_: any[] = [];
const resourceFetchers_: any[] = [];
const kvStores_: KvStore[] = [];
let currentClient_ = 1;
// The line `process.on('unhandledRejection'...` in all the test files is going to
@@ -112,7 +113,7 @@ SyncTargetRegistry.addClass(SyncTargetDropbox);
SyncTargetRegistry.addClass(SyncTargetAmazonS3);
let syncTargetName_ = '';
let syncTargetId_ = null;
let syncTargetId_: number = null;
let sleepTime = 0;
let isNetworkSyncTarget_ = false;
@@ -120,7 +121,7 @@ function syncTargetName() {
return syncTargetName_;
}
function setSyncTargetName(name) {
function setSyncTargetName(name: string) {
if (name === syncTargetName_) return syncTargetName_;
const previousName = syncTargetName_;
syncTargetName_ = name;
@@ -141,20 +142,19 @@ setSyncTargetName('memory');
const syncDir = `${__dirname}/../tests/sync/${suiteName_}`;
// TODO: Should probably update this for Jest?
// let defaultJasmineTimeout = 90 * 1000;
// if (isNetworkSyncTarget_) defaultJasmineTimeout = 60 * 1000 * 10;
// if (typeof jasmine !== 'undefined') jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultJasmineTimeout;
// 90 seconds now that the tests are running in parallel and have been
// split into smaller suites might not be necessary but for now leave it
// anyway.
let defaultJestTimeout = 90 * 1000;
if (isNetworkSyncTarget_) defaultJestTimeout = 60 * 1000 * 10;
jest.setTimeout(defaultJestTimeout);
const dbLogger = new Logger();
dbLogger.addTarget('console');
// dbLogger.addTarget('file', { path: `${logDir}/log.txt` });
dbLogger.addTarget(TargetType.Console);
dbLogger.setLevel(Logger.LEVEL_WARN);
const logger = new Logger();
logger.addTarget('console');
// logger.addTarget('file', { path: `${logDir}/log.txt` });
logger.addTarget(TargetType.Console);
logger.setLevel(Logger.LEVEL_WARN); // Set to DEBUG to display sync process in console
Logger.initializeGlobalLogger(logger);
@@ -184,16 +184,16 @@ function isNetworkSyncTarget() {
return isNetworkSyncTarget_;
}
function sleep(n) {
return new Promise((resolve, reject) => {
function sleep(n: number) {
return new Promise((resolve) => {
shim.setTimeout(() => {
resolve();
}, Math.round(n * 1000));
});
}
function msleep(ms) {
return new Promise((resolve, reject) => {
function msleep(ms: number) {
return new Promise((resolve) => {
shim.setTimeout(() => {
resolve();
}, ms);
@@ -206,9 +206,10 @@ function currentClientId() {
async function afterEachCleanUp() {
await ItemChange.waitForAllSaved();
KeymapService.destroyInstance();
}
async function switchClient(id, options = null) {
async function switchClient(id: number, options: any = null) {
options = Object.assign({}, { keychainEnabled: false }, options);
if (!databases_[id]) throw new Error(`Call setupDatabaseAndSynchronizer(${id}) first!!`);
@@ -233,7 +234,7 @@ async function switchClient(id, options = null) {
Setting.setValue('sync.wipeOutFailSafe', false); // To keep things simple, always disable fail-safe unless explicitely set in the test itself
}
async function clearDatabase(id = null) {
async function clearDatabase(id: number = null) {
if (id === null) id = currentClient_;
if (!databases_[id]) return;
@@ -264,13 +265,19 @@ async function clearDatabase(id = null) {
await databases_[id].transactionExecBatch(queries);
}
async function setupDatabase(id = null, options = null) {
async function setupDatabase(id: number = null, options: any = null) {
options = Object.assign({}, { keychainEnabled: false }, options);
if (id === null) id = currentClient_;
Setting.cancelScheduleSave();
Setting.cache_ = null;
// Note that this was changed from `Setting.cache_ = []` to `await
// Setting.reset()` during the TypeScript conversion. Normally this is
// more correct but something to keep in mind anyway in case there are
// some strange async issue related to settings when the tests are
// running.
await Setting.reset();
if (databases_[id]) {
BaseModel.setDb(databases_[id]);
@@ -295,22 +302,22 @@ async function setupDatabase(id = null, options = null) {
await loadKeychainServiceAndSettings(options.keychainEnabled ? KeychainServiceDriver : KeychainServiceDriverDummy);
}
function resourceDirName(id = null) {
function resourceDirName(id: number = null) {
if (id === null) id = currentClient_;
return `resources-${id}`;
}
function resourceDir(id = null) {
function resourceDir(id: number = null) {
if (id === null) id = currentClient_;
return `${dataDir}/${resourceDirName(id)}`;
}
function pluginDir(id = null) {
function pluginDir(id: number = null) {
if (id === null) id = currentClient_;
return `${dataDir}/plugins-${id}`;
}
async function setupDatabaseAndSynchronizer(id, options = null) {
async function setupDatabaseAndSynchronizer(id: number, options: any = null) {
if (id === null) id = currentClient_;
BaseService.logger_ = logger;
@@ -347,12 +354,12 @@ async function setupDatabaseAndSynchronizer(id, options = null) {
await fileApi().clearRoot();
}
function db(id = null) {
function db(id: number = null) {
if (id === null) id = currentClient_;
return databases_[id];
}
function synchronizer(id = null) {
function synchronizer(id: number = null) {
if (id === null) id = currentClient_;
return synchronizers_[id];
}
@@ -360,7 +367,7 @@ function synchronizer(id = null) {
// This is like calling synchronizer.start() but it handles the
// complexity of passing around the sync context depending on
// the client.
async function synchronizerStart(id = null, extraOptions = null) {
async function synchronizerStart(id: number = null, extraOptions: any = null) {
if (id === null) id = currentClient_;
const context = synchronizerContexts_[id];
const options = Object.assign({}, extraOptions);
@@ -370,41 +377,41 @@ async function synchronizerStart(id = null, extraOptions = null) {
return newContext;
}
function encryptionService(id = null) {
function encryptionService(id: number = null) {
if (id === null) id = currentClient_;
return encryptionServices_[id];
}
function kvStore(id = null) {
function kvStore(id: number = null) {
if (id === null) id = currentClient_;
const o = kvStores_[id];
o.setDb(db(id));
return o;
}
function revisionService(id = null) {
function revisionService(id: number = null) {
if (id === null) id = currentClient_;
return revisionServices_[id];
}
function decryptionWorker(id = null) {
function decryptionWorker(id: number = null) {
if (id === null) id = currentClient_;
const o = decryptionWorkers_[id];
o.setKvStore(kvStore(id));
return o;
}
function resourceService(id = null) {
function resourceService(id: number = null) {
if (id === null) id = currentClient_;
return resourceServices_[id];
}
function resourceFetcher(id = null) {
function resourceFetcher(id: number = null) {
if (id === null) id = currentClient_;
return resourceFetchers_[id];
}
async function loadEncryptionMasterKey(id = null, useExisting = false) {
async function loadEncryptionMasterKey(id: number = null, useExisting = false) {
const service = encryptionService(id);
let masterKey = null;
@@ -487,7 +494,7 @@ function fileApi() {
return fileApis_[syncTargetId_];
}
function objectsEqual(o1, o2) {
function objectsEqual(o1: any, o2: any) {
if (Object.getOwnPropertyNames(o1).length !== Object.getOwnPropertyNames(o2).length) return false;
for (const n in o1) {
if (!o1.hasOwnProperty(n)) continue;
@@ -496,7 +503,7 @@ function objectsEqual(o1, o2) {
return true;
}
async function checkThrowAsync(asyncFn) {
async function checkThrowAsync(asyncFn: Function) {
let hasThrown = false;
try {
await asyncFn();
@@ -506,7 +513,7 @@ async function checkThrowAsync(asyncFn) {
return hasThrown;
}
async function expectThrow(asyncFn, errorCode = undefined) {
async function expectThrow(asyncFn: Function, errorCode: any = undefined) {
let hasThrown = false;
let thrownError = null;
try {
@@ -517,7 +524,7 @@ async function expectThrow(asyncFn, errorCode = undefined) {
}
if (!hasThrown) {
expect('not throw').toBe('throw', 'Expected function to throw an error but did not');
expect('not throw').toBe('throw');
} else if (thrownError.code !== errorCode) {
console.error(thrownError);
expect(`error code: ${thrownError.code}`).toBe(`error code: ${errorCode}`);
@@ -526,7 +533,7 @@ async function expectThrow(asyncFn, errorCode = undefined) {
}
}
async function expectNotThrow(asyncFn) {
async function expectNotThrow(asyncFn: Function) {
let thrownError = null;
try {
await asyncFn();
@@ -536,13 +543,13 @@ async function expectNotThrow(asyncFn) {
if (thrownError) {
console.error(thrownError);
expect(thrownError.message).toBe('', 'Expected function not to throw an error but it did');
expect(thrownError.message).toBe('');
} else {
expect(true).toBe(true);
}
}
function checkThrow(fn) {
function checkThrow(fn: Function) {
let hasThrown = false;
try {
fn();
@@ -552,7 +559,7 @@ function checkThrow(fn) {
return hasThrown;
}
function fileContentEqual(path1, path2) {
function fileContentEqual(path1: string, path2: string) {
const fs = require('fs-extra');
const content1 = fs.readFileSync(path1, 'base64');
const content2 = fs.readFileSync(path2, 'base64');
@@ -591,19 +598,19 @@ async function allSyncTargetItemsEncrypted() {
return totalCount === encryptedCount;
}
function id(a) {
function id(a: any) {
return a.id;
}
function ids(a) {
function ids(a: any[]) {
return a.map(n => n.id);
}
function sortedIds(a) {
function sortedIds(a: any[]) {
return ids(a).sort();
}
function at(a, indexes) {
function at(a: any[], indexes: any[]) {
const out = [];
for (let i = 0; i < indexes.length; i++) {
out.push(a[indexes[i]]);
@@ -611,7 +618,7 @@ function at(a, indexes) {
return out;
}
async function createNTestFolders(n) {
async function createNTestFolders(n: number) {
const folders = [];
for (let i = 0; i < n; i++) {
const folder = await Folder.save({ title: 'folder' });
@@ -621,7 +628,7 @@ async function createNTestFolders(n) {
return folders;
}
async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
async function createNTestNotes(n: number, folder: any, tagIds: string[] = null, title: string = 'note') {
const notes = [];
for (let i = 0; i < n; i++) {
const title_ = n > 1 ? `${title}${i}` : title;
@@ -638,7 +645,7 @@ async function createNTestNotes(n, folder, tagIds = null, title = 'note') {
return notes;
}
async function createNTestTags(n) {
async function createNTestTags(n: number) {
const tags = [];
for (let i = 0; i < n; i++) {
const tag = await Tag.save({ title: 'tag' });
@@ -648,7 +655,7 @@ async function createNTestTags(n) {
return tags;
}
function tempFilePath(ext) {
function tempFilePath(ext: string) {
return `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}.${ext}`;
}
@@ -675,7 +682,7 @@ function newPluginService(appVersion = '1.4') {
return service;
}
function newPluginScript(script) {
function newPluginScript(script: string) {
return `
/* joplin-manifest:
{
@@ -705,6 +712,11 @@ function newPluginScript(script) {
// Application for feature integration testing
class TestApp extends BaseApplication {
private hasGui_: boolean;
private middlewareCalls_: any[];
private logger_: LoggerWrapper;
constructor(hasGui = true) {
super();
this.hasGui_ = hasGui;
@@ -716,7 +728,7 @@ class TestApp extends BaseApplication {
return this.hasGui_;
}
async start(argv) {
async start(argv: any[]) {
this.logger_.info('Test app starting...');
if (!argv.includes('--profile')) {
@@ -737,7 +749,7 @@ class TestApp extends BaseApplication {
this.logger_.info('Test app started...');
}
async generalMiddleware(store, next, action) {
async generalMiddleware(store: any, next: any, action: any) {
this.middlewareCalls_.push(true);
try {
await super.generalMiddleware(store, next, action);

View File

@@ -85,7 +85,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
}
editorRef.current.setSelections(newSelections);
}
editorRef.current.focus();
}, []);
const addListItem = useCallback((string1, defaultText = '') => {
@@ -97,7 +96,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
} else {
wrapSelectionWithStrings(string1, '', defaultText);
}
editorRef.current.focus();
}
}, [wrapSelectionWithStrings]);
@@ -141,7 +139,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
} else {
reg.logger().warn('CodeMirror: unsupported drop item: ', cmd);
}
} else if (cmd.name === 'focus') {
} else if (cmd.name === 'editor.focus') {
editorRef.current.focus();
} else {
commandProcessed = false;
@@ -170,6 +168,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
textItalic: () => wrapSelectionWithStrings('*', '*', _('emphasised text')),
textLink: async () => {
const url = await dialogs.prompt(_('Insert Hyperlink'));
editorRef.current.focus();
if (url) wrapSelectionWithStrings('[', `](${url})`);
},
textCode: () => {

View File

@@ -247,7 +247,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
if (cmd.name === 'insertText') {
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, cmd.value, { bodyOnly: true });
editor.insertContent(result.html);
} else if (cmd.name === 'focus') {
} else if (cmd.name === 'editor.focus') {
editor.focus();
} else if (cmd.name === 'dropItems') {
if (cmd.value.type === 'notes') {

View File

@@ -57,6 +57,7 @@ function styles_(props: Props) {
fontSize: Math.round(theme.textStyle.fontSize * 1.5),
backgroundColor: theme.backgroundColor,
border: 'none',
width: '100%',
},
titleDate: {

View File

@@ -92,6 +92,9 @@ const declarations: CommandDeclaration[] = [
{
name: 'editor.setText',
},
{
name: 'editor.focus',
},
];
export default declarations;

View File

@@ -10,7 +10,7 @@ export const declaration: CommandDeclaration = {
export const runtime = (comp: any): CommandRuntime => {
return {
execute: async () => {
comp.editorRef.current.execCommand({ name: 'focus' });
comp.editorRef.current.execCommand({ name: 'editor.focus' });
},
enabledCondition: 'oneNoteSelected',
};

View File

@@ -55,7 +55,7 @@ export default function styles(props: NoteEditorProps) {
padding: 10,
marginLeft: 5,
marginBottom: 10,
color: theme.colorWarn,
backgroundColor: theme.warningBackgroundColor,
},
resourceWatchBannerLine: {

View File

@@ -161,7 +161,7 @@ export default function useFormNote(dependencies: HookDependencies) {
if (Setting.value(focusSettingName) === 'title') {
if (titleInputRef.current) titleInputRef.current.focus();
} else {
if (editorRef.current) editorRef.current.execCommand({ name: 'focus' });
if (editorRef.current) editorRef.current.execCommand({ name: 'editor.focus' });
}
});
}

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "1.5.3",
"version": "1.5.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,13 +1,14 @@
{
"name": "@joplin/app-desktop",
"version": "1.5.3",
"version": "1.5.4",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
"scripts": {
"dist": "node_modules/.bin/electron-builder",
"dist": "npm run electronRebuild && node_modules/.bin/electron-builder",
"build": "gulp build",
"postinstall": "npm run build && gulp electronRebuild",
"postinstall": "npm run build",
"electronRebuild": "gulp electronRebuild",
"tsc": "node node_modules/typescript/bin/tsc --project tsconfig.json",
"watch": "node node_modules/typescript/bin/tsc --watch --project tsconfig.json",
"start": "gulp build && electron . --env dev --log-level debug --no-welcome --open-dev-tools",

View File

@@ -2,6 +2,24 @@ const fs = require('fs');
const path = require('path');
const electron_notarize = require('electron-notarize');
function execCommand(command) {
const exec = require('child_process').exec;
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
if (error.signal == 'SIGTERM') {
resolve('Process was killed');
} else {
reject(new Error([stdout.trim(), stderr.trim()].join('\n')));
}
} else {
resolve([stdout.trim(), stderr.trim()].join('\n'));
}
});
});
}
module.exports = async function(params) {
if (process.platform !== 'darwin') return;
@@ -48,5 +66,16 @@ module.exports = async function(params) {
ascProvider: process.env.APPLE_ASC_PROVIDER,
});
// It appears that electron-notarize doesn't staple the app, but without
// this we were still getting the malware warning when launching the app.
// Stapling the app means attaching the notarization ticket to it, so that
// if the user is offline, macOS can still check if the app was notarized.
// So it seems to be more or less optional, but at least in our case it
// wasn't.
console.log('Staple notarization ticket to the app...');
const staplerCmd = `xcrun stapler staple "${appPath}"`;
console.log(`> ${staplerCmd}`);
console.log(await execCommand(staplerCmd));
console.log(`Done notarizing ${appId}`);
};

View File

@@ -1,9 +1,9 @@
const TurndownService = require('joplin-turndown');
const TurndownService = require('@joplin/turndown');
const turndownPluginGfm = require('@joplin/turndown-plugin-gfm').gfm;
const markdownUtils = require('./markdownUtils').default;
class HtmlToMd {
parse(html, options = {}) {
const turndownPluginGfm = require('joplin-turndown-plugin-gfm').gfm;
const turndown = new TurndownService({
headingStyle: 'atx',
anchorNames: options.anchorNames ? options.anchorNames.map(n => n.trim().toLowerCase()) : [],
@@ -12,6 +12,7 @@ class HtmlToMd {
bulletListMarker: '-',
emDelimiter: '*',
strongDelimiter: '**',
br: '',
});
turndown.use(turndownPluginGfm);
turndown.remove('script');

View File

@@ -121,6 +121,10 @@ export default class Synchronizer {
}
}
private static reportHasErrors(report: any): boolean {
return !!report && !!report.errors && !!report.errors.length;
}
static reportToLines(report: any) {
const lines = [];
if (report.createLocal) lines.push(_('Created local items: %d.', report.createLocal));
@@ -132,7 +136,7 @@ export default class Synchronizer {
if (report.fetchingTotal && report.fetchingProcessed) lines.push(_('Fetched items: %d/%d.', report.fetchingProcessed, report.fetchingTotal));
if (report.cancelling && !report.completedTime) lines.push(_('Cancelling...'));
if (report.completedTime) lines.push(_('Completed: %s', time.formatMsToLocal(report.completedTime)));
if (report.errors && report.errors.length) lines.push(_('Last error: %s', report.errors[report.errors.length - 1].toString().substr(0, 500)));
if (this.reportHasErrors(report)) lines.push(_('Last error: %s', report.errors[report.errors.length - 1].toString().substr(0, 500)));
return lines;
}
@@ -193,7 +197,7 @@ export default class Synchronizer {
this.logger().info(`Total notes: ${noteCount}`);
this.logger().info(`Total resources: ${resourceCount}`);
if (report.errors && report.errors.length) {
if (Synchronizer.reportHasErrors(report)) {
this.logger().warn('There was some errors:');
for (let i = 0; i < report.errors.length; i++) {
const e = report.errors[i];
@@ -315,6 +319,7 @@ export default class Synchronizer {
const outputContext = Object.assign({}, lastContext);
this.dispatch({ type: 'SYNC_STARTED' });
eventManager.emit('syncStart');
this.logSyncOperation('starting', null, null, `Starting synchronisation to target ${syncTargetId}... [${synchronizationId}]`);
@@ -899,11 +904,14 @@ export default class Synchronizer {
await this.logSyncSummary(this.progressReport_);
eventManager.emit('syncComplete', {
withErrors: Synchronizer.reportHasErrors(this.progressReport_),
});
this.onProgress_ = function() {};
this.progressReport_ = {};
this.dispatch({ type: 'SYNC_COMPLETED', isFullSync: this.isFullSync(syncSteps) });
eventManager.emit('syncComplete');
this.state_ = 'idle';

View File

@@ -6,4 +6,4 @@ describe('dummy', () => {
expect(1).toBe(1);
});
});
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
const locales = {};
const stats = {};
var locales = {};
var stats = {};
locales['en_GB'] = require('./en_GB.json');
locales['ar'] = require('./ar.json');
locales['bg_BG'] = require('./bg_BG.json');
@@ -15,6 +15,7 @@ locales['es_ES'] = require('./es_ES.json');
locales['et_EE'] = require('./et_EE.json');
locales['eu'] = require('./eu.json');
locales['fa'] = require('./fa.json');
locales['fi_FI'] = require('./fi_FI.json');
locales['fr_FR'] = require('./fr_FR.json');
locales['gl_ES'] = require('./gl_ES.json');
locales['hr_HR'] = require('./hr_HR.json');
@@ -38,42 +39,43 @@ locales['tr_TR'] = require('./tr_TR.json');
locales['vi'] = require('./vi.json');
locales['zh_CN'] = require('./zh_CN.json');
locales['zh_TW'] = require('./zh_TW.json');
stats['ar'] = { 'percentDone': 78 };
stats['eu'] = { 'percentDone': 33 };
stats['bs_BA'] = { 'percentDone': 82 };
stats['bg_BG'] = { 'percentDone': 65 };
stats['ca'] = { 'percentDone': 95 };
stats['hr_HR'] = { 'percentDone': 27 };
stats['cs_CZ'] = { 'percentDone': 98 };
stats['da_DK'] = { 'percentDone': 72 };
stats['de_DE'] = { 'percentDone': 97 };
stats['et_EE'] = { 'percentDone': 65 };
stats['en_GB'] = { 'percentDone': 100 };
stats['en_US'] = { 'percentDone': 100 };
stats['es_ES'] = { 'percentDone': 98 };
stats['eo'] = { 'percentDone': 37 };
stats['fr_FR'] = { 'percentDone': 98 };
stats['gl_ES'] = { 'percentDone': 42 };
stats['id_ID'] = { 'percentDone': 92 };
stats['it_IT'] = { 'percentDone': 98 };
stats['nl_NL'] = { 'percentDone': 94 };
stats['nl_BE'] = { 'percentDone': 33 };
stats['nb_NO'] = { 'percentDone': 87 };
stats['fa'] = { 'percentDone': 82 };
stats['pl_PL'] = { 'percentDone': 97 };
stats['pt_PT'] = { 'percentDone': 98 };
stats['pt_BR'] = { 'percentDone': 96 };
stats['ro'] = { 'percentDone': 77 };
stats['sl_SI'] = { 'percentDone': 41 };
stats['sv'] = { 'percentDone': 70 };
stats['th_TH'] = { 'percentDone': 52 };
stats['vi'] = { 'percentDone': 84 };
stats['tr_TR'] = { 'percentDone': 97 };
stats['el_GR'] = { 'percentDone': 95 };
stats['ru_RU'] = { 'percentDone': 94 };
stats['sr_RS'] = { 'percentDone': 70 };
stats['zh_CN'] = { 'percentDone': 95 };
stats['zh_TW'] = { 'percentDone': 94 };
stats['ja_JP'] = { 'percentDone': 99 };
stats['ko'] = { 'percentDone': 99 };
module.exports = { locales: locales, stats: stats };
stats['ar'] = {"percentDone":77};
stats['eu'] = {"percentDone":33};
stats['bs_BA'] = {"percentDone":79};
stats['bg_BG'] = {"percentDone":64};
stats['ca'] = {"percentDone":92};
stats['hr_HR'] = {"percentDone":26};
stats['cs_CZ'] = {"percentDone":96};
stats['da_DK'] = {"percentDone":79};
stats['de_DE'] = {"percentDone":96};
stats['et_EE'] = {"percentDone":63};
stats['en_GB'] = {"percentDone":100};
stats['en_US'] = {"percentDone":100};
stats['es_ES'] = {"percentDone":96};
stats['eo'] = {"percentDone":36};
stats['fi_FI'] = {"percentDone":97};
stats['fr_FR'] = {"percentDone":96};
stats['gl_ES'] = {"percentDone":42};
stats['id_ID'] = {"percentDone":88};
stats['it_IT'] = {"percentDone":97};
stats['nl_BE'] = {"percentDone":33};
stats['nl_NL'] = {"percentDone":96};
stats['nb_NO'] = {"percentDone":85};
stats['fa'] = {"percentDone":79};
stats['pl_PL'] = {"percentDone":95};
stats['pt_BR'] = {"percentDone":93};
stats['pt_PT'] = {"percentDone":95};
stats['ro'] = {"percentDone":74};
stats['sl_SI'] = {"percentDone":41};
stats['sv'] = {"percentDone":68};
stats['th_TH'] = {"percentDone":50};
stats['vi'] = {"percentDone":82};
stats['tr_TR'] = {"percentDone":94};
stats['el_GR'] = {"percentDone":92};
stats['ru_RU'] = {"percentDone":92};
stats['sr_RS'] = {"percentDone":69};
stats['zh_CN'] = {"percentDone":97};
stats['zh_TW'] = {"percentDone":91};
stats['ja_JP'] = {"percentDone":97};
stats['ko'] = {"percentDone":97};
module.exports = { locales: locales, stats: stats };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -590,6 +590,8 @@ class Setting extends BaseModel {
'markdown.plugin.softbreaks': { value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable soft breaks')}${wysiwygYes}` },
'markdown.plugin.typographer': { value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable typographer support')}${wysiwygYes}` },
'markdown.plugin.linkify': { value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable Linkify')}${wysiwygYes}` },
'markdown.plugin.katex': { value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable math expressions')}${wysiwygYes}` },
'markdown.plugin.fountain': { value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable Fountain syntax support')}${wysiwygYes}` },
'markdown.plugin.mermaid': { value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable Mermaid diagrams support')}${wysiwygYes}` },

File diff suppressed because it is too large Load Diff

View File

@@ -17,14 +17,16 @@
},
"devDependencies": {
"@types/jest": "^26.0.15",
"jest": "^26.6.3",
"@types/node": "^14.14.6",
"jest": "^26.6.3",
"typescript": "^4.0.5"
},
"dependencies": {
"@joplin/fork-htmlparser2": "^4.1.8",
"@joplin/fork-sax": "^1.2.12",
"@joplin/renderer": "^1.0.17",
"@joplin/turndown": "^4.0.30",
"@joplin/turndown-plugin-gfm": "^1.0.12",
"async-mutex": "^0.1.3",
"aws-sdk": "^2.588.0",
"base-64": "^0.1.0",
@@ -45,8 +47,6 @@
"image-data-uri": "^2.0.0",
"image-type": "^3.0.0",
"immer": "^7.0.14",
"joplin-turndown": "^4.0.30",
"joplin-turndown-plugin-gfm": "^1.0.12",
"levenshtein": "^1.0.5",
"lodash": "^4.17.20",
"markdown-it": "^10.0.0",

View File

@@ -1,274 +1,16 @@
import eventManager from '../eventManager';
import shim from '../shim';
import { _ } from '../locale';
import keysRegExp from './KeymapService_keysRegExp';
import keycodeToElectronMap from './KeymapService_keycodeToElectronMap';
const BaseService = require('./BaseService').default;
const keysRegExp = /^([0-9A-Z)!@#$%^&*(:+<_>?~{|}";=,\-./`[\\\]']|F1*[1-9]|F10|F2[0-4]|Plus|Space|Tab|Backspace|Delete|Insert|Return|Enter|Up|Down|Left|Right|Home|End|PageUp|PageDown|Escape|Esc|VolumeUp|VolumeDown|VolumeMute|MediaNextTrack|MediaPreviousTrack|MediaStop|MediaPlayPause|PrintScreen|Numlock|Scrolllock|Capslock|num([0-9]|dec|add|sub|mult|div))$/;
const modifiersRegExp = {
darwin: /^(Ctrl|Option|Shift|Cmd)$/,
default: /^(Ctrl|Alt|AltGr|Shift|Super)$/,
};
const keycodeToElectronMap = [
'', // [0]
'', // [1]
'', // [2]
'', // [3]
'', // [4]
'', // [5]
'', // [6]
'', // [7]
'Backspace', // [8]
'Tab', // [9]
'', // [10]
'', // [11]
'Clear', // [12]
'Enter', // [13]
'', // [14]
'', // [15]
'Shift', // [16]
'Ctrl', // [17]
'Alt', // [18]
'', // [19]
'Capslock', // [20]
'', // [21]
'', // [22]
'', // [23]
'', // [24]
'', // [25]
'', // [26]
'Esc', // [27]
'', // [28]
'', // [29]
'', // [30]
'', // [31]
'Space', // [32]
'PageUp', // [33]
'PageDown', // [34]
'End', // [35]
'Home', // [36]
'Left', // [37]
'Up', // [38]
'Right', // [39]
'Down', // [40]
'', // [41]
'', // [42]
'', // [43]
'PrintScreen', // [44]
'Insert', // [45]
'Delete', // [46]
'', // [47]
'0', // [48]
'1', // [49]
'2', // [50]
'3', // [51]
'4', // [52]
'5', // [53]
'6', // [54]
'7', // [55]
'8', // [56]
'9', // [57]
':', // [58]
';', // [59]
'<', // [60]
'=', // [61]
'>', // [62]
'?', // [63]
'@', // [64]
'A', // [65]
'B', // [66]
'C', // [67]
'D', // [68]
'E', // [69]
'F', // [70]
'G', // [71]
'H', // [72]
'I', // [73]
'J', // [74]
'K', // [75]
'L', // [76]
'M', // [77]
'N', // [78]
'O', // [79]
'P', // [80]
'Q', // [81]
'R', // [82]
'S', // [83]
'T', // [84]
'U', // [85]
'V', // [86]
'W', // [87]
'X', // [88]
'Y', // [89]
'Z', // [90]
'Super', // [91] Super: Windows Key (Windows) or Command Key (Mac)
'', // [92]
'ContextMenu', // [93]
'', // [94]
'', // [95]
'num0', // [96]
'num1', // [97]
'num2', // [98]
'num3', // [99]
'num4', // [100]
'num5', // [101]
'num6', // [102]
'num7', // [103]
'num8', // [104]
'num9', // [105]
'nummult', // [106] *
'numadd', // [107] +
'', // [108]
'numsub', // [109] -
'numdec', // [110]
'numdiv', // [111] ÷
'F1', // [112]
'F2', // [113]
'F3', // [114]
'F4', // [115]
'F5', // [116]
'F6', // [117]
'F7', // [118]
'F8', // [119]
'F9', // [120]
'F10', // [121]
'F11', // [122]
'F12', // [123]
'F13', // [124]
'F14', // [125]
'F15', // [126]
'F16', // [127]
'F17', // [128]
'F18', // [129]
'F19', // [130]
'F20', // [131]
'F21', // [132]
'F22', // [133]
'F23', // [134]
'F24', // [135]
'', // [136]
'', // [137]
'', // [138]
'', // [139]
'', // [140]
'', // [141]
'', // [142]
'', // [143]
'Numlock', // [144]
'Scrolllock', // [145]
'', // [146]
'', // [147]
'', // [148]
'', // [149]
'', // [150]
'', // [151]
'', // [152]
'', // [153]
'', // [154]
'', // [155]
'', // [156]
'', // [157]
'', // [158]
'', // [159]
'', // [160]
'!', // [161]
'"', // [162]
'#', // [163]
'$', // [164]
'%', // [165]
'&', // [166]
'_', // [167]
'(', // [168]
')', // [169]
'*', // [170]
'Plus', // [171]
'|', // [172]
'-', // [173]
'{', // [174]
'}', // [175]
'~', // [176]
'', // [177]
'', // [178]
'', // [179]
'', // [180]
'VolumeMute', // [181]
'VolumeDown', // [182]
'VolumeUp', // [183]
'', // [184]
'', // [185]
';', // [186]
'=', // [187]
',', // [188]
'-', // [189]
'.', // [190]
'/', // [191]
'`', // [192]
'', // [193]
'', // [194]
'', // [195]
'', // [196]
'', // [197]
'', // [198]
'', // [199]
'', // [200]
'', // [201]
'', // [202]
'', // [203]
'', // [204]
'', // [205]
'', // [206]
'', // [207]
'', // [208]
'', // [209]
'', // [210]
'', // [211]
'', // [212]
'', // [213]
'', // [214]
'', // [215]
'', // [216]
'', // [217]
'', // [218]
'[', // [219]
'\\', // [220]
']', // [221]
'\'', // [222]
'', // [223]
'', // [224]
'AltGr', // [225]
'', // [226]
'', // [227]
'', // [228]
'', // [229]
'', // [230]
'', // [231]
'', // [232]
'', // [233]
'', // [234]
'', // [235]
'', // [236]
'', // [237]
'', // [238]
'', // [239]
'', // [240]
'', // [241]
'', // [242]
'', // [243]
'', // [244]
'', // [245]
'', // [246]
'', // [247]
'', // [248]
'', // [249]
'', // [250]
'', // [251]
'', // [252]
'', // [253]
'', // [254]
'', // [255]
];
const defaultKeymapItems = {
darwin: [
{ accelerator: 'Cmd+N', command: 'newNote' },

View File

@@ -0,0 +1,262 @@
// This is the keycode map for Electron.
const keycodeToElectronMap = [
'', // [0]
'', // [1]
'', // [2]
'', // [3]
'', // [4]
'', // [5]
'', // [6]
'', // [7]
'Backspace', // [8]
'Tab', // [9]
'', // [10]
'', // [11]
'Clear', // [12]
'Enter', // [13]
'', // [14]
'', // [15]
'Shift', // [16]
'Ctrl', // [17]
'Alt', // [18]
'', // [19]
'Capslock', // [20]
'', // [21]
'', // [22]
'', // [23]
'', // [24]
'', // [25]
'', // [26]
'Esc', // [27]
'', // [28]
'', // [29]
'', // [30]
'', // [31]
'Space', // [32]
'PageUp', // [33]
'PageDown', // [34]
'End', // [35]
'Home', // [36]
'Left', // [37]
'Up', // [38]
'Right', // [39]
'Down', // [40]
'', // [41]
'', // [42]
'', // [43]
'PrintScreen', // [44]
'Insert', // [45]
'Delete', // [46]
'', // [47]
'0', // [48]
'1', // [49]
'2', // [50]
'3', // [51]
'4', // [52]
'5', // [53]
'6', // [54]
'7', // [55]
'8', // [56]
'9', // [57]
':', // [58]
';', // [59]
'<', // [60]
'=', // [61]
'>', // [62]
'?', // [63]
'@', // [64]
'A', // [65]
'B', // [66]
'C', // [67]
'D', // [68]
'E', // [69]
'F', // [70]
'G', // [71]
'H', // [72]
'I', // [73]
'J', // [74]
'K', // [75]
'L', // [76]
'M', // [77]
'N', // [78]
'O', // [79]
'P', // [80]
'Q', // [81]
'R', // [82]
'S', // [83]
'T', // [84]
'U', // [85]
'V', // [86]
'W', // [87]
'X', // [88]
'Y', // [89]
'Z', // [90]
'Super', // [91] Super: Windows Key (Windows) or Command Key (Mac)
'', // [92]
'ContextMenu', // [93]
'', // [94]
'', // [95]
'num0', // [96]
'num1', // [97]
'num2', // [98]
'num3', // [99]
'num4', // [100]
'num5', // [101]
'num6', // [102]
'num7', // [103]
'num8', // [104]
'num9', // [105]
'nummult', // [106] *
'numadd', // [107] +
'', // [108]
'numsub', // [109] -
'numdec', // [110]
'numdiv', // [111] ÷
'F1', // [112]
'F2', // [113]
'F3', // [114]
'F4', // [115]
'F5', // [116]
'F6', // [117]
'F7', // [118]
'F8', // [119]
'F9', // [120]
'F10', // [121]
'F11', // [122]
'F12', // [123]
'F13', // [124]
'F14', // [125]
'F15', // [126]
'F16', // [127]
'F17', // [128]
'F18', // [129]
'F19', // [130]
'F20', // [131]
'F21', // [132]
'F22', // [133]
'F23', // [134]
'F24', // [135]
'', // [136]
'', // [137]
'', // [138]
'', // [139]
'', // [140]
'', // [141]
'', // [142]
'', // [143]
'Numlock', // [144]
'Scrolllock', // [145]
'', // [146]
'', // [147]
'', // [148]
'', // [149]
'', // [150]
'', // [151]
'', // [152]
'', // [153]
'', // [154]
'', // [155]
'', // [156]
'', // [157]
'', // [158]
'', // [159]
'', // [160]
'!', // [161]
'"', // [162]
'#', // [163]
'$', // [164]
'%', // [165]
'&', // [166]
'_', // [167]
'(', // [168]
')', // [169]
'*', // [170]
'Plus', // [171]
'|', // [172]
'-', // [173]
'{', // [174]
'}', // [175]
'~', // [176]
'', // [177]
'', // [178]
'', // [179]
'', // [180]
'VolumeMute', // [181]
'VolumeDown', // [182]
'VolumeUp', // [183]
'', // [184]
'', // [185]
';', // [186]
'=', // [187]
',', // [188]
'-', // [189]
'.', // [190]
'/', // [191]
'`', // [192]
'', // [193]
'', // [194]
'', // [195]
'', // [196]
'', // [197]
'', // [198]
'', // [199]
'', // [200]
'', // [201]
'', // [202]
'', // [203]
'', // [204]
'', // [205]
'', // [206]
'', // [207]
'', // [208]
'', // [209]
'', // [210]
'', // [211]
'', // [212]
'', // [213]
'', // [214]
'', // [215]
'', // [216]
'', // [217]
'', // [218]
'[', // [219]
'\\', // [220]
']', // [221]
'\'', // [222]
'', // [223]
'', // [224]
'AltGr', // [225]
'', // [226]
'', // [227]
'', // [228]
'', // [229]
'', // [230]
'', // [231]
'', // [232]
'', // [233]
'', // [234]
'', // [235]
'', // [236]
'', // [237]
'', // [238]
'', // [239]
'', // [240]
'', // [241]
'', // [242]
'', // [243]
'', // [244]
'', // [245]
'', // [246]
'', // [247]
'', // [248]
'', // [249]
'', // [250]
'', // [251]
'', // [252]
'', // [253]
'', // [254]
'', // [255]
];
export default keycodeToElectronMap;

View File

@@ -0,0 +1,9 @@
// We move this regex outside KeymapService because it makes gettext parsing
// fail. In fact it doesn't fail at the regex itself but at the next backtick
// into the code. Probably their parser see a backtick in the regex and opens a
// JS template string, while it shouldn't.
// https://discourse.joplinapp.org/t/translations/12832?u=laurent
const keysRegExp = /^([0-9A-Z)!@#$%^&*(:+<_>?~{|}";=,\-./`[\\\]']|F1*[1-9]|F10|F2[0-4]|Plus|Space|Tab|Backspace|Delete|Insert|Return|Enter|Up|Down|Left|Right|Home|End|PageUp|PageDown|Escape|Esc|VolumeUp|VolumeDown|VolumeMute|MediaNextTrack|MediaPreviousTrack|MediaStop|MediaPlayPause|PrintScreen|Numlock|Scrolllock|Capslock|num([0-9]|dec|add|sub|mult|div))$/;
export default keysRegExp;

View File

@@ -23,7 +23,7 @@ export default class KvStore extends BaseService {
this.instance_ = null;
}
private constructor() {
public constructor() {
super();
this.incMutex_ = new Mutex();
}

View File

@@ -33,6 +33,30 @@ export default class ToolbarButtonUtils {
return this.service_;
}
// Editor commands will focus the editor after they're executed
private isEditorCommand(commandName: string) {
return (commandName.indexOf('editor.') === 0 ||
// These commands are grandfathered in, but in the future
// all editor commands should start with "editor."
// WARNING: Some commands such as textLink are not defined here
// because they are more complex and handle focus manually
commandName === 'textCopy' ||
commandName === 'textCut' ||
commandName === 'textPaste' ||
commandName === 'textSelectAll' ||
commandName === 'textBold' ||
commandName === 'textItalic' ||
commandName === 'textCode' ||
commandName === 'attachFile' ||
commandName === 'textNumberedList' ||
commandName === 'textBulletedList' ||
commandName === 'textCheckbox' ||
commandName === 'textHeading' ||
commandName === 'textHorizontalRule' ||
commandName === 'insertDateTime'
);
}
private commandToToolbarButton(commandName: string, whenClauseContext: any): ToolbarButtonInfo {
const newEnabled = this.service.isEnabled(commandName, whenClauseContext);
const newTitle = this.service.title(commandName);
@@ -52,8 +76,11 @@ export default class ToolbarButtonUtils {
tooltip: this.service.label(commandName),
iconName: command.declaration.iconName,
enabled: newEnabled,
onClick: () => {
onClick: async () => {
void this.service.execute(commandName);
if (this.isEditorCommand(commandName)) {
void this.service.execute('editor.focus');
}
},
title: newTitle,
};

View File

@@ -14,7 +14,7 @@ export default class JoplinViewsMenuItems {
private store: any;
private plugin: Plugin;
constructor(plugin: Plugin, store: any) {
public constructor(plugin: Plugin, store: any) {
this.store = store;
this.plugin = plugin;
}
@@ -22,7 +22,7 @@ export default class JoplinViewsMenuItems {
/**
* Creates a new menu item and associate it with the given command. You can specify under which menu the item should appear using the `location` parameter.
*/
async create(id: string, commandName: string, location: MenuItemLocation = MenuItemLocation.Tools, options: CreateMenuItemOptions = null) {
public async create(id: string, commandName: string, location: MenuItemLocation = MenuItemLocation.Tools, options: CreateMenuItemOptions = null) {
if (typeof location !== 'string') {
this.plugin.deprecationNotice('1.5', 'Creating a view without an ID is deprecated. To fix it, change your call to `joplin.views.menuItem.create("my-unique-id", ...)`');
options = location as any;
@@ -35,8 +35,17 @@ export default class JoplinViewsMenuItems {
const controller = new MenuItemController(handle, this.plugin.id, this.store, commandName, location);
this.plugin.addViewController(controller);
// Register the command with the keymap service - not that if no
// accelerator is provided, we still register the command, so that
// it appears in the keymap editor, which will allow the user to
// set a custom shortcut.
//
// https://discourse.joplinapp.org/t/plugin-note-tabs/12752/39
if (options && options.accelerator) {
KeymapService.instance().registerCommandAccelerator(commandName, options.accelerator);
} else {
KeymapService.instance().registerCommandAccelerator(commandName, null);
}
}

View File

@@ -19,7 +19,14 @@ interface ItemChangeEvent {
event: ItemChangeEventType;
}
interface SyncStartEvent {
// Tells whether there were errors during sync or not. The log will
// have the complete information about any error.
withErrors: boolean;
}
type ItemChangeHandler = (event: ItemChangeEvent)=> void;
type SyncStartHandler = (event: SyncStartEvent)=> void;
/**
* The workspace service provides access to all the parts of Joplin that
@@ -80,8 +87,15 @@ export default class JoplinWorkspace {
/**
* Called when an alarm associated with a to-do is triggered.
*/
public async onNoteAlarmTrigger(callback: Function): Promise<Disposable> {
return makeListener(eventManager, 'noteAlarmTrigger', callback);
public async onNoteAlarmTrigger(handler: Function): Promise<Disposable> {
return makeListener(eventManager, 'noteAlarmTrigger', handler);
}
/**
* Called when the synchronisation process is starting.
*/
public async onSyncStart(handler: SyncStartHandler): Promise<Disposable> {
return makeListener(eventManager, 'syncStart', handler);
}
/**

View File

@@ -41,7 +41,7 @@ const theme: Theme = {
searchMarkerBackgroundColor: '#F7D26E',
searchMarkerColor: 'black',
warningBackgroundColor: '#CC6600',
warningBackgroundColor: '#013F74',
tableBackgroundColor: 'rgb(40, 41, 42)',
codeBackgroundColor: 'rgb(47, 48, 49)',

View File

@@ -378,7 +378,7 @@ export default class MdToHtml {
const markdownIt = new MarkdownIt({
breaks: !this.pluginEnabled('softbreaks'),
typographer: this.pluginEnabled('typographer'),
linkify: true,
linkify: this.pluginEnabled('linkify'),
html: true,
highlight: (str: string, lang: string) => {
let outputCodeHtml = '';
@@ -471,7 +471,7 @@ export default class MdToHtml {
}
}
setupLinkify(markdownIt);
if (this.pluginEnabled('linkify')) setupLinkify(markdownIt);
const renderedBody = markdownIt.render(body, context);

View File

@@ -26,4 +26,10 @@ module.exports = function(markdownIt) {
return BAD_PROTO_RE.test(str) ? (GOOD_DATA_RE.test(str) ? true : false) : true;
};
markdownIt.linkify.set({
'fuzzyLink': false,
'fuzzyIP': false,
'fuzzyEmail': false,
});
};

View File

@@ -130,7 +130,7 @@ async function createPotFile(potFilePath) {
if (isMac()) xgettextPath = executablePath('xgettext'); // Needs to have been installed with `brew install gettext`
const cmd = `${xgettextPath} ${args.join(' ')}`;
const result = await execCommand(cmd);
if (result) console.error(result);
if (result && result.trim()) console.error(result.trim());
await removePoHeaderDate(potFilePath);
}
@@ -140,7 +140,7 @@ async function mergePotToPo(potFilePath, poFilePath) {
const command = `${msgmergePath} -U "${poFilePath}" "${potFilePath}"`;
const result = await execCommand(command);
if (result) console.error(result);
if (result && result.trim()) console.info(result.trim());
await removePoHeaderDate(poFilePath);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More