1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-30 20:39:46 +02:00

Compare commits

..

57 Commits

Author SHA1 Message Date
Laurent Cozic
6d5d9323bd CLI v1.3.1 2020-10-23 16:04:34 +01:00
Laurent Cozic
76063a6284 Android release v1.3.9 2020-10-23 16:03:13 +01:00
Laurent Cozic
4119924e57 Electron release v1.3.9 2020-10-23 15:57:29 +01:00
Laurent Cozic
537336754c All: Sort tags in a case-insensitive way 2020-10-23 15:48:11 +01:00
Laurent Cozic
06f73919bd Desktop: Fixed Cut menu item and test units 2020-10-23 13:21:37 +01:00
Laurent Cozic
3f3e46081c Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-10-22 16:34:45 +01:00
Laurent Cozic
68e4b4eaad macOS: Fixes #3404: Show context menu option to copy a link 2020-10-22 16:32:13 +01:00
Gen Neko
9dcb4b51e5 All: Translation: Update ja_JP.po (#3967) 2020-10-22 11:05:28 -04:00
Laurent Cozic
8543849ea1 Tools: Fixed tests 2020-10-22 15:55:29 +01:00
Laurent Cozic
6ce5240e12 Plugins: Fixed tests 2020-10-22 14:51:59 +01:00
Rory O’Kane
5bc25aefce Desktop: Make “update is available” dialog box easier to use (#3877) 2020-10-22 12:25:06 +01:00
Naveen M V
b737ca7471 All: Fix search filters when language is in Korean or with accents (#3947) 2020-10-22 12:16:47 +01:00
Laurent Cozic
a5d7366f94 Desktop: Fix invalid tag state issue when importing notes or syncing 2020-10-22 11:21:16 +01:00
Laurent Cozic
98f822d89c Cleaned up plugin doc 2020-10-21 22:52:58 +01:00
Laurent Cozic
c33a8250ee Desktop: Added openProfileDirectory command and menu item 2020-10-21 22:10:21 +01:00
Laurent Cozic
adad406696 Update translations 2020-10-21 21:54:47 +01:00
Laurent Cozic
d82eec0fa4 Tools: Render translator names as link to prevent website template from breaking 2020-10-21 21:53:41 +01:00
Laurent Cozic
c93f474547 Merge branch 'release-1.3' of github.com:laurent22/joplin into release-1.3 2020-10-21 21:30:29 +01:00
Laurent Cozic
0afd4a6234 Doc: Fixed typo 2020-10-21 21:23:31 +01:00
Laurent Cozic
f42786a840 Android release v1.3.8 2020-10-21 18:31:12 +01:00
Laurent Cozic
1c1f044966 Electron release v1.3.8 2020-10-21 18:19:33 +01:00
Laurent Cozic
ad7a80e260 Api: Allow preserving timestamps when updating a note 2020-10-21 18:12:36 +01:00
Laurent Cozic
5e040c062c Desktop: Fixes #3962: Certain commands no longer worked. 2020-10-21 17:22:29 +01:00
Laurent Cozic
0cede5f90a Desktop: Display more info while an ENEX file is being imported 2020-10-21 16:55:52 +01:00
Laurent Cozic
8dc0deb2a4 Desktop, Cli: Fixes #3958: Fixed freeze when importing ENEX as HTML, and fixed potential error when importing resources 2020-10-21 12:02:06 +01:00
Laurent Cozic
1ca44b8f44 Desktop: Made toolbar buttons bigger and swap order of bullet and number lists 2020-10-21 10:39:53 +01:00
Laurent Cozic
4ba9e60194 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-10-21 10:12:13 +01:00
Laurent Cozic
9d0bb4257f Desktop: Regression: Fixed format of copied version info 2020-10-21 10:10:18 +01:00
Alessandro Bernardello
1a273b9bca All: Translation: Update it_IT.po (#3956)
* Updated italian translation

* Updated translator name and email
2020-10-21 01:03:23 -04:00
Laurent Cozic
d9e93cd6c4 Doc: Update plugin doc 2020-10-21 01:46:53 +01:00
Laurent Cozic
5d39860707 Plugins: Allow custom commands to return a result 2020-10-21 01:43:06 +01:00
Laurent Cozic
60a6f714bc Update website 2020-10-21 00:56:03 +01:00
Laurent Cozic
6eebeca259 Tools: updated plugin types 2020-10-21 00:55:10 +01:00
Laurent Cozic
995034c53f Update plugin templates 2020-10-21 00:35:06 +01:00
Laurent Cozic
45a0981d05 Updated website 2020-10-21 00:27:11 +01:00
Laurent Cozic
3d8577a689 Plugins: Added support for content scripts
- For now, supports Markdown-it plugins
- Also fixed slow rendering of notes in some cases
- Simplified how Markdown-It plugins are created and cleaned MdToHtml code

commit 89576de289
Merge: c75aa21f 5292fc14
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 21 00:23:00 2020 +0100

    Merge branch 'release-1.3' into plugin_content_scripts

commit c75aa21ffd
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 21 00:19:52 2020 +0100

    Fixed tests

commit 075187729d
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 21 00:11:53 2020 +0100

    Fixed tests

commit 14696b8c65
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 23:27:58 2020 +0100

    Fixed slow rendering of note

commit 61c09f5bf8
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 22:35:21 2020 +0100

    Clean up

commit 9f7ea7d865
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 20:05:31 2020 +0100

    Updated doc

commit 98bf3bde8d
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 19:56:34 2020 +0100

    Finished converting plugins

commit fe90d92e01
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 20 17:52:02 2020 +0100

    Simplified how Markdown-It plugins are created

commit 47c7b864cb
Author: Laurent Cozic <laurent@cozic.net>
Date:   Mon Oct 19 16:40:11 2020 +0100

    Clean up rules

commit d927a238bb
Author: Laurent Cozic <laurent@cozic.net>
Date:   Mon Oct 19 14:29:40 2020 +0100

    Fixed tests

commit 388a56c5dd
Author: Laurent Cozic <laurent@cozic.net>
Date:   Mon Oct 19 14:00:47 2020 +0100

    Add support for content scripts
2020-10-21 00:23:55 +01:00
Laurent Cozic
5292fc1402 Tools: Escape HTML when generating changelog 2020-10-20 17:16:09 +01:00
Laurent Cozic
03063f1137 All: Fixed setting issue that would cause a password to be saved in plain text in the database, even when the keychain is working 2020-10-20 16:37:14 +01:00
Laurent Cozic
b125a768b8 Tools: Added test units for keychains on macOS and Windows 2020-10-20 16:16:18 +01:00
Laurent Cozic
a721f170e4 Doc: Added info about search filters 2020-10-20 12:12:00 +01:00
Laurent Cozic
76cd69ea16 Electron release v1.3.7 2020-10-20 12:01:12 +01:00
Laurent Cozic
45d4f277e2 Merge branch 'dev' into release-1.3 2020-10-20 12:00:39 +01:00
Naveen M V
fc2a52aa1a Desktop, Cli; Fix notebook search filter (#3946) 2020-10-20 11:54:46 +01:00
Roman Musin
b3e5a1e48d Android: do not show long press menu on press and drag (#3939) 2020-10-20 11:51:24 +01:00
Laurent Cozic
45eb902030 Fixed tests 2020-10-20 11:49:15 +01:00
Ian Slinger
456f7ac00c Desktop, Cli: Import <strike>,<s> tags (strikethrough) from Evernote (#3936) 2020-10-20 11:47:48 +01:00
Aaron
a93bda71fe All: Resolves #3691: Added support for a custom S3 URL (#3921) 2020-10-20 11:44:11 +01:00
Alkindi42
0f9d92dd3d Doc: add archlinux package for pre-release in docs (#3875) 2020-10-20 11:42:41 +01:00
Laurent Cozic
5543e9ef64 Merge branch 'release-1.3' of https://github.com/laurent22/joplin into release-1.3 2020-10-20 11:14:58 +01:00
Laurent Cozic
22dd613660 Revert "Plugins: Adding support for command boolean expressions"
This reverts commit f8f46db910.

Feature was implemented in 3a57cfea02
2020-10-20 11:13:56 +01:00
Laurent Cozic
f7502fe34b Electron release v1.3.6 2020-10-19 23:25:59 +01:00
Laurent Cozic
8254206f44 Desktop: Fixes #3893 (maybe): Trying to fix sidebar performance issue when there are many notebooks or tags 2020-10-19 23:24:40 +01:00
Laurent Cozic
3a57cfea02 Desktop: Simplified and improve command service, and added command palette
- Commands "enabled" state is now expressed using a "when-clause" like in VSCode
- A command palette has been added to the Tools menu
2020-10-18 21:52:10 +01:00
Helmut K. C. Tessarek
71bf0437c1 Desktop: Tray: Exit -> Quit (#3945) 2020-10-18 12:57:04 +01:00
Tomáš Bambas
eca4e24362 All: Translation: Update cs_CZ.po (#3940) 2020-10-17 14:01:32 -04:00
Andros Fenollosa
9a6efb7b37 All: Translation: Update es_ES.po (#3929)
* Update locale es

* Finish translate
2020-10-17 14:00:48 -04:00
jduar
4b666cbbd2 All: Translation: Update pt-PT.po (#3924)
* Updated the Portuguese (pt-PT) translation.

* Updated translator name and email.
2020-10-17 13:58:49 -04:00
477 changed files with 27345 additions and 17800 deletions

View File

@@ -64,10 +64,13 @@ CliClient/build/
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/app/services/plugins/PluginRunner.js
CliClient/tests/fsDriver.js
CliClient/tests/InMemoryCache.js
CliClient/tests/MdToHtml.js
CliClient/tests/models_Setting.js
CliClient/tests/services_CommandService.js
CliClient/tests/services_InteropService.js
CliClient/tests/services_keychainService.js
CliClient/tests/services_PluginService.js
CliClient/tests/services_rest_Api.js
CliClient/tests/services/plugins/api/JoplinSetting.js
@@ -78,6 +81,7 @@ ElectronClient/app.js
ElectronClient/bridge.js
ElectronClient/commands/copyDevCommand.js
ElectronClient/commands/focusElement.js
ElectronClient/commands/openProfileDirectory.js
ElectronClient/commands/startExternalEditing.js
ElectronClient/commands/stopExternalEditing.js
ElectronClient/commands/toggleExternalEditing.js
@@ -180,6 +184,7 @@ ElectronClient/gui/SideBar/styles/index.js
ElectronClient/gui/StatusScreen/StatusScreen.js
ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/TagList.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
ElectronClient/gui/ToolbarBase.js
@@ -214,22 +219,36 @@ ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/components/SelectDateTimeDialog.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/fs-driver-node.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/InMemoryCache.js
ReactNativeClient/lib/joplin-renderer/MarkupToHtml.js
ReactNativeClient/lib/joplin-renderer/MdToHtml.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/code_inline.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fountain.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/highlight_keywords.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/html_image.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/image.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/katex.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/link_open.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
ReactNativeClient/lib/joplin-renderer/noteStyle.js
ReactNativeClient/lib/joplin-renderer/pathUtils.js
ReactNativeClient/lib/JoplinServerApi.js
ReactNativeClient/lib/locale.js
ReactNativeClient/lib/Logger.js
ReactNativeClient/lib/markdownUtils.js
ReactNativeClient/lib/markupLanguageUtils.js
ReactNativeClient/lib/models/Alarm.js
ReactNativeClient/lib/models/Setting.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/path-utils.js
ReactNativeClient/lib/PoorManIntervals.js
ReactNativeClient/lib/reducer.js
ReactNativeClient/lib/services/AlarmService.js
@@ -290,6 +309,7 @@ ReactNativeClient/lib/services/plugins/PluginService.js
ReactNativeClient/lib/services/plugins/reducer.js
ReactNativeClient/lib/services/plugins/sandboxProxy.js
ReactNativeClient/lib/services/plugins/ToolbarButtonController.js
ReactNativeClient/lib/services/plugins/utils/contentScriptsToRendererRules.js
ReactNativeClient/lib/services/plugins/utils/createViewHandle.js
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js

20
.gitignore vendored
View File

@@ -58,10 +58,13 @@ plugin_types/
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/app/services/plugins/PluginRunner.js
CliClient/tests/fsDriver.js
CliClient/tests/InMemoryCache.js
CliClient/tests/MdToHtml.js
CliClient/tests/models_Setting.js
CliClient/tests/services_CommandService.js
CliClient/tests/services_InteropService.js
CliClient/tests/services_keychainService.js
CliClient/tests/services_PluginService.js
CliClient/tests/services_rest_Api.js
CliClient/tests/services/plugins/api/JoplinSetting.js
@@ -72,6 +75,7 @@ ElectronClient/app.js
ElectronClient/bridge.js
ElectronClient/commands/copyDevCommand.js
ElectronClient/commands/focusElement.js
ElectronClient/commands/openProfileDirectory.js
ElectronClient/commands/startExternalEditing.js
ElectronClient/commands/stopExternalEditing.js
ElectronClient/commands/toggleExternalEditing.js
@@ -174,6 +178,7 @@ ElectronClient/gui/SideBar/styles/index.js
ElectronClient/gui/StatusScreen/StatusScreen.js
ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/TagList.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
ElectronClient/gui/ToolbarBase.js
@@ -208,22 +213,36 @@ ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/components/SelectDateTimeDialog.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/fs-driver-node.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/InMemoryCache.js
ReactNativeClient/lib/joplin-renderer/MarkupToHtml.js
ReactNativeClient/lib/joplin-renderer/MdToHtml.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/code_inline.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fountain.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/highlight_keywords.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/html_image.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/image.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/katex.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/link_open.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
ReactNativeClient/lib/joplin-renderer/noteStyle.js
ReactNativeClient/lib/joplin-renderer/pathUtils.js
ReactNativeClient/lib/JoplinServerApi.js
ReactNativeClient/lib/locale.js
ReactNativeClient/lib/Logger.js
ReactNativeClient/lib/markdownUtils.js
ReactNativeClient/lib/markupLanguageUtils.js
ReactNativeClient/lib/models/Alarm.js
ReactNativeClient/lib/models/Setting.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/path-utils.js
ReactNativeClient/lib/PoorManIntervals.js
ReactNativeClient/lib/reducer.js
ReactNativeClient/lib/services/AlarmService.js
@@ -284,6 +303,7 @@ ReactNativeClient/lib/services/plugins/PluginService.js
ReactNativeClient/lib/services/plugins/reducer.js
ReactNativeClient/lib/services/plugins/sandboxProxy.js
ReactNativeClient/lib/services/plugins/ToolbarButtonController.js
ReactNativeClient/lib/services/plugins/utils/contentScriptsToRendererRules.js
ReactNativeClient/lib/services/plugins/utils/createViewHandle.js
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js

20
.ignore
View File

@@ -7,10 +7,13 @@
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/app/services/plugins/PluginRunner.js
CliClient/tests/fsDriver.js
CliClient/tests/InMemoryCache.js
CliClient/tests/MdToHtml.js
CliClient/tests/models_Setting.js
CliClient/tests/services_CommandService.js
CliClient/tests/services_InteropService.js
CliClient/tests/services_keychainService.js
CliClient/tests/services_PluginService.js
CliClient/tests/services_rest_Api.js
CliClient/tests/services/plugins/api/JoplinSetting.js
@@ -21,6 +24,7 @@ ElectronClient/app.js
ElectronClient/bridge.js
ElectronClient/commands/copyDevCommand.js
ElectronClient/commands/focusElement.js
ElectronClient/commands/openProfileDirectory.js
ElectronClient/commands/startExternalEditing.js
ElectronClient/commands/stopExternalEditing.js
ElectronClient/commands/toggleExternalEditing.js
@@ -123,6 +127,7 @@ ElectronClient/gui/SideBar/styles/index.js
ElectronClient/gui/StatusScreen/StatusScreen.js
ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/TagList.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
ElectronClient/gui/ToolbarBase.js
@@ -157,22 +162,36 @@ ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/components/SelectDateTimeDialog.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/fs-driver-node.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/InMemoryCache.js
ReactNativeClient/lib/joplin-renderer/MarkupToHtml.js
ReactNativeClient/lib/joplin-renderer/MdToHtml.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/code_inline.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fountain.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/highlight_keywords.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/html_image.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/image.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/katex.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/link_open.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
ReactNativeClient/lib/joplin-renderer/noteStyle.js
ReactNativeClient/lib/joplin-renderer/pathUtils.js
ReactNativeClient/lib/JoplinServerApi.js
ReactNativeClient/lib/locale.js
ReactNativeClient/lib/Logger.js
ReactNativeClient/lib/markdownUtils.js
ReactNativeClient/lib/markupLanguageUtils.js
ReactNativeClient/lib/models/Alarm.js
ReactNativeClient/lib/models/Setting.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/path-utils.js
ReactNativeClient/lib/PoorManIntervals.js
ReactNativeClient/lib/reducer.js
ReactNativeClient/lib/services/AlarmService.js
@@ -233,6 +252,7 @@ ReactNativeClient/lib/services/plugins/PluginService.js
ReactNativeClient/lib/services/plugins/reducer.js
ReactNativeClient/lib/services/plugins/sandboxProxy.js
ReactNativeClient/lib/services/plugins/ToolbarButtonController.js
ReactNativeClient/lib/services/plugins/utils/contentScriptsToRendererRules.js
ReactNativeClient/lib/services/plugins/utils/createViewHandle.js
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js

View File

@@ -8,7 +8,7 @@ const Note = require('lib/models/Note.js');
const Tag = require('lib/models/Tag.js');
const Setting = require('lib/models/Setting').default;
const { reg } = require('lib/registry.js');
const { fileExtension } = require('lib/path-utils.js');
const { fileExtension } = require('lib/path-utils');
const { _ } = require('lib/locale');
const fs = require('fs-extra');
const { cliUtils } = require('./cli-utils.js');

View File

@@ -1,5 +1,5 @@
const fs = require('fs-extra');
const { fileExtension, dirname } = require('lib/path-utils.js');
const { fileExtension, dirname } = require('lib/path-utils');
const wrap_ = require('word-wrap');
const { languageCode } = require('lib/locale');

View File

@@ -2,7 +2,7 @@
const fs = require('fs-extra');
const Logger = require('lib/Logger').default;
const { dirname } = require('lib/path-utils.js');
const { dirname } = require('lib/path-utils');
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
const { JoplinDatabase } = require('lib/joplin-database.js');
const BaseModel = require('lib/BaseModel.js');

View File

@@ -5,7 +5,7 @@ const DecryptionWorker = require('lib/services/DecryptionWorker');
const BaseItem = require('lib/models/BaseItem');
const Setting = require('lib/models/Setting').default;
const shim = require('lib/shim').default;
const pathUtils = require('lib/path-utils.js');
const pathUtils = require('lib/path-utils');
const imageType = require('image-type');
const readChunk = require('read-chunk');

View File

@@ -3,8 +3,8 @@
const { time } = require('lib/time-utils.js');
const Logger = require('lib/Logger').default;
const Resource = require('lib/models/Resource.js');
const { dirname } = require('lib/path-utils.js');
const { FsDriverNode } = require('./fs-driver-node.js');
const { dirname } = require('lib/path-utils');
const FsDriverNode = require('lib/fs-driver-node').default;
const lodash = require('lodash');
const exec = require('child_process').exec;
const fs = require('fs-extra');

View File

@@ -24,7 +24,7 @@ const MasterKey = require('lib/models/MasterKey');
const Setting = require('lib/models/Setting').default;
const Revision = require('lib/models/Revision.js');
const Logger = require('lib/Logger').default;
const { FsDriverNode } = require('lib/fs-driver-node.js');
const FsDriverNode = require('lib/fs-driver-node').default;
const { shimInit } = require('lib/shim-init-node.js');
const { _ } = require('lib/locale');
const { FileApiDriverLocal } = require('lib/file-api-driver-local.js');

View File

@@ -54,15 +54,25 @@ export default class PluginRunner extends BasePluginRunner {
};
}
async run(plugin:Plugin, sandbox:Global) {
const vmSandbox = vm.createContext(this.newSandboxProxy(plugin.id, sandbox));
async run(plugin:Plugin, sandbox:Global):Promise<void> {
return new Promise((resolve:Function, reject:Function) => {
const onStarted = () => {
plugin.off('started', onStarted);
resolve();
};
try {
vm.runInContext(plugin.scriptText, vmSandbox);
} catch (error) {
this.logger().error(`In plugin ${plugin.id}:`, error);
return;
}
plugin.on('started', onStarted);
const vmSandbox = vm.createContext(this.newSandboxProxy(plugin.id, sandbox));
try {
vm.runInContext(plugin.scriptText, vmSandbox);
} catch (error) {
reject(error);
// this.logger().error(`In plugin ${plugin.id}:`, error);
// return;
}
});
}
}

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

@@ -38,42 +38,42 @@ 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":80};
stats['eu'] = {"percentDone":34};
stats['bs_BA'] = {"percentDone":83};
stats['bg_BG'] = {"percentDone":66};
stats['ca'] = {"percentDone":96};
stats['ar'] = {"percentDone":79};
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":82};
stats['da_DK'] = {"percentDone":74};
stats['de_DE'] = {"percentDone":98};
stats['et_EE'] = {"percentDone":66};
stats['cs_CZ'] = {"percentDone":99};
stats['da_DK'] = {"percentDone":73};
stats['de_DE'] = {"percentDone":97};
stats['et_EE'] = {"percentDone":65};
stats['en_GB'] = {"percentDone":100};
stats['en_US'] = {"percentDone":100};
stats['es_ES'] = {"percentDone":95};
stats['eo'] = {"percentDone":38};
stats['fr_FR'] = {"percentDone":99};
stats['gl_ES'] = {"percentDone":43};
stats['id_ID'] = {"percentDone":93};
stats['it_IT'] = {"percentDone":90};
stats['nl_BE'] = {"percentDone":34};
stats['nl_NL'] = {"percentDone":95};
stats['nb_NO'] = {"percentDone":88};
stats['fa'] = {"percentDone":83};
stats['pl_PL'] = {"percentDone":98};
stats['pt_PT'] = {"percentDone":88};
stats['pt_BR'] = {"percentDone":96};
stats['es_ES'] = {"percentDone":99};
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_BE'] = {"percentDone":33};
stats['nl_NL'] = {"percentDone":94};
stats['nb_NO'] = {"percentDone":87};
stats['fa'] = {"percentDone":82};
stats['pl_PL'] = {"percentDone":97};
stats['pt_PT'] = {"percentDone":98};
stats['pt_BR'] = {"percentDone":95};
stats['ro'] = {"percentDone":77};
stats['sl_SI'] = {"percentDone":42};
stats['sv'] = {"percentDone":70};
stats['th_TH'] = {"percentDone":52};
stats['vi'] = {"percentDone":85};
stats['tr_TR'] = {"percentDone":98};
stats['el_GR'] = {"percentDone":96};
stats['ru_RU'] = {"percentDone":95};
stats['sr_RS'] = {"percentDone":71};
stats['zh_CN'] = {"percentDone":96};
stats['zh_TW'] = {"percentDone":95};
stats['ja_JP'] = {"percentDone":98};
stats['ko'] = {"percentDone":98};
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":97};
stats['ko'] = {"percentDone":99};
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

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

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

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

View File

@@ -1,6 +1,6 @@
{
"name": "joplin",
"version": "1.3.0",
"version": "1.3.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -28,7 +28,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.3.0",
"version": "1.3.1",
"bin": {
"joplin": "./main.js"
},

View File

@@ -3,6 +3,7 @@ require('app-module-path').addPath(__dirname);
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
const shim = require('lib/shim').default;
const { enexXmlToHtml } = require('lib/import-enex-html-gen.js');
const cleanHtml = require('clean-html');
process.on('unhandledRejection', (reason, p) => {
console.warn('Unhandled Rejection at: Promise', p, 'reason:', reason);
@@ -19,6 +20,20 @@ const audioResource = {
title: 'audio test',
};
// All the test HTML files are beautified ones, so we need to run
// this before the comparison. Before, beautifying was done by `enexXmlToHtml`
// but that was removed due to problems with the clean-html package.
const beautifyHtml = (html) => {
return new Promise((resolve) => {
try {
cleanHtml.clean(html, { wrap: 0 }, (...cleanedHtml) => resolve(cleanedHtml.join('')));
} catch (error) {
console.warn(`Could not clean HTML - the "unclean" version will be used: ${error.message}: ${html.trim().substr(0, 512).replace(/[\n\r]/g, ' ')}...`);
resolve([html].join(''));
}
});
};
/**
* Tests the importer for a single note, checking that the result of
* processing the given `.enex` input file matches the contents of the given
@@ -38,7 +53,7 @@ const compareOutputToExpected = (options) => {
it(testTitle, asyncTest(async () => {
const enexInput = await shim.fsDriver().readFile(inputFile);
const expectedOutput = await shim.fsDriver().readFile(outputFile);
const actualOutput = await enexXmlToHtml(enexInput, options.resources);
const actualOutput = await beautifyHtml(await enexXmlToHtml(enexInput, options.resources));
expect(actualOutput).toEqual(expectedOutput);
}));

View File

@@ -4,7 +4,7 @@ require('app-module-path').addPath(__dirname);
const os = require('os');
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { filename } = require('lib/path-utils');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');

View File

@@ -4,7 +4,7 @@ require('app-module-path').addPath(__dirname);
const os = require('os');
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { filename } = require('lib/path-utils');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');

View File

@@ -4,7 +4,7 @@ require('app-module-path').addPath(__dirname);
const os = require('os');
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { filename } = require('lib/path-utils');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');

View File

@@ -1,7 +1,7 @@
require('app-module-path').addPath(__dirname);
const { asyncTest } = require('test-utils.js');
const MarkupToHtml = require('lib/joplin-renderer/MarkupToHtml');
const MarkupToHtml = require('lib/joplin-renderer/MarkupToHtml').default;
describe('MarkupToHtml', function() {

View File

@@ -1,24 +1,11 @@
/* eslint-disable no-unused-vars */
require('app-module-path').addPath(__dirname);
const os = require('os');
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const BaseModel = require('lib/BaseModel.js');
const { filename } = require('lib/path-utils');
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
const shim = require('lib/shim').default;
const MdToHtml = require('lib/joplin-renderer/MdToHtml');
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
const MdToHtml = require('lib/joplin-renderer/MdToHtml').default;
const { themeStyle } = require('lib/theme');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
function newTestMdToHtml(options = null) {
function newTestMdToHtml(options:any = null) {
options = {
ResourceModel: {
isResourceUrl: () => false,
@@ -32,7 +19,7 @@ function newTestMdToHtml(options = null) {
describe('MdToHtml', function() {
beforeEach(async (done) => {
beforeEach(async (done:Function) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
@@ -52,14 +39,14 @@ describe('MdToHtml', function() {
// if (mdFilename !== 'sanitize_9.md') continue;
const mdToHtmlOptions = {
const mdToHtmlOptions:any = {
bodyOnly: true,
};
if (mdFilename === 'checkbox_alternative.md') {
mdToHtmlOptions.plugins = {
checkbox: {
renderingType: 2,
checkboxRenderingType: 2,
},
};
}
@@ -96,7 +83,7 @@ describe('MdToHtml', function() {
}));
it('should return enabled plugin assets', asyncTest(async () => {
const pluginOptions = {};
const pluginOptions:any = {};
const pluginNames = MdToHtml.pluginNames();
for (const n of pluginNames) pluginOptions[n] = { enabled: false };
@@ -126,7 +113,7 @@ describe('MdToHtml', function() {
// In this case, the HTML contains both the style and
// the rendered markdown wrapped in a DIV.
const result = await mdToHtml.render('just **testing**');
expect(result.cssStrings.length).toBe(0);
expect(result.cssStrings.length).toBeGreaterThan(0);
expect(result.html.indexOf('rendered-md') >= 0).toBe(true);
}));
@@ -137,7 +124,7 @@ describe('MdToHtml', function() {
// with no wrapper and no style.
// The style is instead in the cssStrings property.
const result = await mdToHtml.render('just **testing**', null, { bodyOnly: true });
expect(result.cssStrings.length).toBe(1);
expect(result.cssStrings.length).toBeGreaterThan(0);
expect(result.html.trim()).toBe('just <strong>testing</strong>');
}));
@@ -147,7 +134,7 @@ describe('MdToHtml', function() {
// It is similar to the bodyOnly option, excepts that
// the rendered Markdown is wrapped in a DIV
const result = await mdToHtml.render('just **testing**', null, { splitted: true });
expect(result.cssStrings.length).toBe(1);
expect(result.cssStrings.length).toBeGreaterThan(0);
expect(result.html.trim()).toBe('<div id="rendered-md"><p>just <strong>testing</strong></p>\n</div>');
}));

View File

@@ -0,0 +1,29 @@
import FsDriverNode from 'lib/fs-driver-node';
import shim from 'lib/shim';
const { expectThrow } = require('test-utils.js');
// On Windows, path.resolve is going to convert a path such as
// /tmp/file.txt to c:\tmp\file.txt
function platformPath(path:string) {
if (shim.isWindows()) {
return `C:${path.replace(/\//g, '\\')}`;
} else {
return path;
}
}
describe('fsDriver', function() {
it('should resolveRelativePathWithinDir', () => {
const fsDriver = new FsDriverNode();
expect(fsDriver.resolveRelativePathWithinDir('/test/temp', './my/file.txt')).toBe(platformPath('/test/temp/my/file.txt'));
expect(fsDriver.resolveRelativePathWithinDir('/', './test')).toBe(platformPath('/test'));
expect(fsDriver.resolveRelativePathWithinDir('/test', 'myfile.txt')).toBe(platformPath('/test/myfile.txt'));
expect(fsDriver.resolveRelativePathWithinDir('/test/temp', './mydir/../test.txt')).toBe(platformPath('/test/temp/test.txt'));
expectThrow(() => fsDriver.resolveRelativePathWithinDir('/test/temp', '../myfile.txt'));
expectThrow(() => fsDriver.resolveRelativePathWithinDir('/test/temp', './mydir/../../test.txt'));
expectThrow(() => fsDriver.resolveRelativePathWithinDir('/test/temp', '/var/local/no.txt'));
});
});

View File

@@ -2,7 +2,7 @@
require('app-module-path').addPath(__dirname);
const { extractExecutablePath, quotePath, unquotePath, friendlySafeFilename, toFileProtocolPath } = require('lib/path-utils.js');
const { extractExecutablePath, quotePath, unquotePath, friendlySafeFilename, toFileProtocolPath } = require('lib/path-utils');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
process.on('unhandledRejection', (reason, p) => {

View File

@@ -299,7 +299,7 @@ describe('services_KeymapService', () => {
],
[
{ command: 'showLocalSearch', accelerator: 'Option+Cmd+S' },
{ command: 'print', accelerator: 'Cmd+G' /* Default of gotoAnything */ },
{ command: 'print', accelerator: 'Cmd+P' /* Default of gotoAnything */ },
{ command: 'focusElementNoteTitle', accelerator: 'Option+Shift+Cmd+J' },
],
];
@@ -317,7 +317,7 @@ describe('services_KeymapService', () => {
],
[
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
{ command: 'print', accelerator: 'Ctrl+G' /* Default of gotoAnything */ },
{ command: 'print', accelerator: 'Ctrl+P' /* Default of gotoAnything */ },
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J' },
],
];

View File

@@ -1,8 +1,11 @@
import PluginRunner from '../app/services/plugins/PluginRunner';
import PluginService from 'lib/services/plugins/PluginService';
import { ContentScriptType } from 'lib/services/plugins/api/types';
import MdToHtml from 'lib/joplin-renderer/MdToHtml';
import shim from 'lib/shim';
require('app-module-path').addPath(__dirname);
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow } = require('test-utils.js');
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, createTempDir } = require('test-utils.js');
const Note = require('lib/models/Note');
const Folder = require('lib/models/Folder');
@@ -60,6 +63,9 @@ describe('services_PluginService', function() {
const allFolders = await Folder.all();
expect(allFolders.length).toBe(1);
// If you have an error here, it might mean you need to run `npm i` from
// the "withExternalModules" folder. Not clear exactly why.
expect(allFolders[0].title).toBe(' foo');
}));
@@ -148,4 +154,54 @@ describe('services_PluginService', function() {
}
}));
it('should register a Markdown-it plugin', asyncTest(async () => {
const tempDir = await createTempDir();
const contentScriptPath = `${tempDir}/markdownItTestPlugin.js`;
await shim.fsDriver().copy(`${testPluginDir}/content_script/src/markdownItTestPlugin.js`, contentScriptPath);
const service = newPluginService();
const plugin = await service.loadPluginFromString('example', tempDir, `
/* joplin-manifest:
{
"manifest_version": 1,
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "Laurent Cozic",
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.plugins.registerContentScript('markdownItPlugin', 'justtesting', './markdownItTestPlugin.js');
},
});
`);
await service.runPlugin(plugin);
const contentScripts = plugin.contentScriptsByType(ContentScriptType.MarkdownItPlugin);
expect(contentScripts.length).toBe(1);
expect(!!contentScripts[0].path).toBe(true);
const contentScript = contentScripts[0];
const mdToHtml = new MdToHtml();
const module = require(contentScript.path).default;
mdToHtml.loadExtraRendererRule(contentScript.id, module({}));
const result = await mdToHtml.render([
'```justtesting',
'something',
'```',
].join('\n'));
expect(result.html.includes('JUST TESTING: something')).toBe(true);
await shim.fsDriver().remove(tempDir);
}));
});

View File

@@ -1,60 +0,0 @@
/* eslint-disable no-unused-vars */
require('app-module-path').addPath(__dirname);
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const shim = require('lib/shim').default;
const Setting = require('lib/models/Setting').default;
const KeychainService = require('lib/services/keychain/KeychainService').default;
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
function describeIfCompatible(name, fn) {
if (['win32', 'darwin'].includes(shim.platformName())) {
return describe(name, fn);
}
}
describeIfCompatible('services_KeychainService', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1, { keychainEnabled: true });
await switchClient(1, { keychainEnabled: true });
await Setting.deleteKeychainPasswords();
done();
});
afterEach(async (done) => {
await Setting.deleteKeychainPasswords();
done();
});
it('should be enabled on macOS and Windows', asyncTest(async () => {
expect(Setting.value('keychain.supported')).toBe(1);
}));
it('should set, get and delete passwords', asyncTest(async () => {
const service = KeychainService.instance();
const isSet = await service.setPassword('zz_testunit', 'password');
expect(isSet).toBe(true);
const password = await service.password('zz_testunit');
expect(password).toBe('password');
await service.deletePassword('zz_testunit');
expect(await service.password('zz_testunit')).toBe(null);
}));
it('should save and load secure settings', asyncTest(async () => {
Setting.setObjectValue('encryption.passwordCache', 'testing', '123456');
await Setting.saveAll();
await Setting.load();
const passwords = Setting.value('encryption.passwordCache');
expect(passwords.testing).toBe('123456');
}));
});

View File

@@ -0,0 +1,94 @@
import KeychainService from 'lib/services/keychain/KeychainService';
import shim from 'lib/shim';
import Setting from 'lib/models/Setting';
const { db, asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
function describeIfCompatible(name:string, fn:any) {
if (['win32', 'darwin'].includes(shim.platformName())) {
return describe(name, fn);
}
}
describeIfCompatible('services_KeychainService', function() {
beforeEach(async (done:Function) => {
await setupDatabaseAndSynchronizer(1, { keychainEnabled: true });
await switchClient(1, { keychainEnabled: true });
await Setting.deleteKeychainPasswords();
done();
});
afterEach(async (done:Function) => {
await Setting.deleteKeychainPasswords();
done();
});
it('should be enabled on macOS and Windows', asyncTest(async () => {
expect(Setting.value('keychain.supported')).toBe(1);
}));
it('should set, get and delete passwords', asyncTest(async () => {
const service = KeychainService.instance();
const isSet = await service.setPassword('zz_testunit', 'password');
expect(isSet).toBe(true);
const password = await service.password('zz_testunit');
expect(password).toBe('password');
await service.deletePassword('zz_testunit');
expect(await service.password('zz_testunit')).toBe(null);
}));
it('should save and load secure settings', asyncTest(async () => {
Setting.setObjectValue('encryption.passwordCache', 'testing', '123456');
await Setting.saveAll();
await Setting.load();
const passwords = Setting.value('encryption.passwordCache');
expect(passwords.testing).toBe('123456');
}));
it('should delete db settings if they have been saved in keychain', asyncTest(async () => {
// First save some secure settings and make sure it ends up in the databse
KeychainService.instance().enabled = false;
Setting.setValue('sync.5.password', 'password');
await Setting.saveAll();
{
// Check that it is in the database
const row = await db().selectOne('SELECT * FROM settings WHERE key = "sync.5.password"');
expect(row.value).toBe('password');
}
KeychainService.instance().enabled = true;
// Change any setting to make sure a save operation is triggered
Setting.setValue('sync.5.path', '/tmp');
// Save the settings - now db secure keys should have been cleared and moved to keychain
await Setting.saveAll();
{
// Check that it's been removed from the database
const row = await db().selectOne('SELECT * FROM settings WHERE key = "sync.5.password"');
expect(row).toBe(undefined);
}
// However we should still get it via the Setting class, since it will use the keychain
expect(Setting.value('sync.5.password')).toBe('password');
// Now do it again - because there was a bug that would cause the second attempt to save to the db instead
Setting.setValue('sync.5.username', 'john');
await Setting.saveAll();
{
// Check that it's been removed from the database
const row = await db().selectOne('SELECT * FROM settings WHERE key = "sync.5.password"');
expect(row).toBe(undefined);
}
}));
});

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