You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-24 20:19:10 +02:00
Compare commits
163 Commits
plugin-gen
...
plugin_sys
Author | SHA1 | Date | |
---|---|---|---|
|
bfae770b19 | ||
|
e570f7a226 | ||
|
9b28a8995f | ||
|
197f509f5d | ||
|
4c83d7aa75 | ||
|
17e053b358 | ||
|
a29c93634d | ||
|
a5f5bfcfec | ||
|
b509329383 | ||
|
91c7abed42 | ||
|
54fda6ac97 | ||
|
341eefebaf | ||
|
af714cbdac | ||
|
6a0bf15c28 | ||
|
5a2bdad348 | ||
|
fd08bfdd86 | ||
|
1a5cead659 | ||
|
85df133386 | ||
|
869d11e113 | ||
|
d7a01d3965 | ||
|
989036241d | ||
|
433cef1827 | ||
|
433d34f62b | ||
|
e7ec33bbf9 | ||
|
a29f42d78d | ||
|
74ed234ab9 | ||
|
86b76ccb77 | ||
|
29aedf8480 | ||
|
9486f5e0d2 | ||
|
9a458431b8 | ||
|
2c9db9d18c | ||
|
ae9c535842 | ||
|
a518da587e | ||
|
92e6e00d9e | ||
|
b64c9cf18a | ||
|
275d6e230d | ||
|
ab8ce15c33 | ||
|
3fb6179587 | ||
|
28cc38064c | ||
|
1fa5ab2b96 | ||
|
15f4e635d9 | ||
|
7a79d7ef7e | ||
|
776e7dfe3f | ||
|
790b622cbc | ||
|
89117b4ee9 | ||
|
c245517e0f | ||
|
31db95d0c4 | ||
|
2cd50de065 | ||
|
6dcb7e2605 | ||
|
9c9bd4ba51 | ||
|
71e6964945 | ||
|
97dc2fa6bd | ||
|
161e112e7b | ||
|
c93a6f86cd | ||
|
9bb178b9d9 | ||
|
8087bc5280 | ||
|
100aaab58d | ||
|
126c7b5a75 | ||
|
d448ea3a02 | ||
|
555727e5fe | ||
|
77eceea426 | ||
|
a09c6f152c | ||
|
3830195752 | ||
|
c9594065c3 | ||
|
360d3bbff9 | ||
|
6fde8dfe52 | ||
|
de2ccfbfe0 | ||
|
31f53b12fd | ||
|
d45b280ada | ||
|
b5a137545e | ||
|
4e80dbb7a7 | ||
|
90b0c99806 | ||
|
c8c0c3af46 | ||
|
110de50bf9 | ||
|
b7e110d888 | ||
|
f1c557cb43 | ||
|
43e9fc92c9 | ||
|
10fa331731 | ||
|
cc8e122de3 | ||
|
bca5fd8db9 | ||
|
13101f7d9b | ||
|
4f2884a0f7 | ||
|
4872f1419c | ||
|
fdcaab3caf | ||
|
9f2c4b938f | ||
|
8be65acf7d | ||
|
e05aa433e4 | ||
|
ccfb0b43d6 | ||
|
4211e962c6 | ||
|
6b54c4244b | ||
|
1d5a4bd381 | ||
|
86a1103a64 | ||
|
45edaaa96f | ||
|
b7b158aa94 | ||
|
e6bc55b6f8 | ||
|
111092791c | ||
|
4e91e01ddc | ||
|
44dce6c6c3 | ||
|
b25ad50a1b | ||
|
e2e3be66ee | ||
|
4b3119ebba | ||
|
1712a67e2e | ||
|
cd563b050c | ||
|
4426f2dbec | ||
|
0fbbf2eee0 | ||
|
2fdad2fe80 | ||
|
0249ff48ca | ||
|
142fc02f9c | ||
|
842b123285 | ||
|
a4aca68b85 | ||
|
1397af0692 | ||
|
5da760dd0c | ||
|
511d58d3af | ||
|
a1c9e675ad | ||
|
0349ad0b80 | ||
|
9d8411a25e | ||
|
754ba2267a | ||
|
4cdac308d1 | ||
|
c0d5c7c282 | ||
|
f9296992bf | ||
|
5b06ebde1e | ||
|
d309c75974 | ||
|
807c89a42f | ||
|
0b8350e9ea | ||
|
49e7be8924 | ||
|
810c63e3b2 | ||
|
d917ca5551 | ||
|
ec642300ab | ||
|
9034d646bf | ||
|
96f6bbb035 | ||
|
e14ed655d2 | ||
|
54e5323f54 | ||
|
ef58affed1 | ||
|
76fa87d878 | ||
|
2db2225788 | ||
|
425c1763f4 | ||
|
044f2eac6a | ||
|
281f135125 | ||
|
6c88f8b8ae | ||
|
832abcddf0 | ||
|
e6c481f45c | ||
|
11fecfb83a | ||
|
2facc9868e | ||
|
7b9ad9d1c3 | ||
|
3b96a99f3e | ||
|
575ce5128b | ||
|
dece28da35 | ||
|
2ffc429971 | ||
|
8baa125842 | ||
|
6b6092ffc7 | ||
|
714c912aff | ||
|
ebf8b744e1 | ||
|
1039e98396 | ||
|
8f00538cb1 | ||
|
2b530a3ff9 | ||
|
d089511aa6 | ||
|
450c8dbf22 | ||
|
94d87285dc | ||
|
ffeb7d0ecd | ||
|
aba92857cb | ||
|
5918c81dbb | ||
|
819d9fd977 | ||
|
ad80e074de |
112
.eslintignore
112
.eslintignore
@@ -59,15 +59,47 @@ Tools/node_modules
|
||||
Tools/PortableAppsLauncher
|
||||
Modules/TinyMCE/IconPack/postinstall.js
|
||||
Modules/TinyMCE/langs/
|
||||
CliClient/build/
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
CliClient/app/LinkSelector.js
|
||||
CliClient/build/LinkSelector.js
|
||||
CliClient/app/services/plugins/PluginRunner.js
|
||||
CliClient/tests/models_Setting.js
|
||||
CliClient/tests/services_CommandService.js
|
||||
CliClient/tests/services_InteropService.js
|
||||
CliClient/tests/services_PluginService.js
|
||||
CliClient/tests/services/plugins/sandboxProxy.js
|
||||
CliClient/tests/support/plugins/codemirror_test/global.d.js
|
||||
CliClient/tests/support/plugins/codemirror_test/src/index.js
|
||||
CliClient/tests/support/plugins/dialog/global.d.js
|
||||
CliClient/tests/support/plugins/dialog/src/index.js
|
||||
CliClient/tests/support/plugins/events/global.d.js
|
||||
CliClient/tests/support/plugins/events/src/index.js
|
||||
CliClient/tests/support/plugins/json_export/global.d.js
|
||||
CliClient/tests/support/plugins/json_export/src/index.js
|
||||
CliClient/tests/support/plugins/markdown_plugin/global.d.js
|
||||
CliClient/tests/support/plugins/markdown_plugin/src/index.js
|
||||
CliClient/tests/support/plugins/multi_selection/global.d.js
|
||||
CliClient/tests/support/plugins/multi_selection/src/index.js
|
||||
CliClient/tests/support/plugins/register_command/global.d.js
|
||||
CliClient/tests/support/plugins/register_command/src/index.js
|
||||
CliClient/tests/support/plugins/selected_text/global.d.js
|
||||
CliClient/tests/support/plugins/selected_text/src/index.js
|
||||
CliClient/tests/support/plugins/settings/global.d.js
|
||||
CliClient/tests/support/plugins/settings/src/index.js
|
||||
CliClient/tests/support/plugins/toc/global.d.js
|
||||
CliClient/tests/support/plugins/toc/src/index.js
|
||||
CliClient/tests/support/plugins/withExternalModules/global.d.js
|
||||
CliClient/tests/support/plugins/withExternalModules/src/index.js
|
||||
CliClient/tests/synchronizer_LockHandler.js
|
||||
CliClient/tests/synchronizer_MigrationHandler.js
|
||||
ElectronClient/app.js
|
||||
ElectronClient/bridge.js
|
||||
ElectronClient/commands/copyDevCommand.js
|
||||
ElectronClient/commands/focusElement.js
|
||||
ElectronClient/commands/startExternalEditing.js
|
||||
ElectronClient/commands/stopExternalEditing.js
|
||||
ElectronClient/ElectronAppWrapper.js
|
||||
ElectronClient/global.d.js
|
||||
ElectronClient/gui/Button/Button.js
|
||||
ElectronClient/gui/ConfigScreen/ButtonBar.js
|
||||
@@ -103,6 +135,7 @@ ElectronClient/gui/MainScreen/commands/toggleNoteList.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleSidebar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
@@ -138,7 +171,7 @@ ElectronClient/gui/NoteEditor/utils/useFormNote.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteToolbarButtons.js
|
||||
ElectronClient/gui/NoteEditor/utils/usePluginServiceRegistration.js
|
||||
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
|
||||
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
|
||||
@@ -154,6 +187,7 @@ ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
ElectronClient/gui/ResizableLayout/ResizableLayout.js
|
||||
ElectronClient/gui/ResourceScreen.js
|
||||
ElectronClient/gui/Root_UpgradeSyncTarget.js
|
||||
ElectronClient/gui/Root.js
|
||||
ElectronClient/gui/SearchBar/hooks/useSearch.js
|
||||
ElectronClient/gui/SearchBar/SearchBar.js
|
||||
ElectronClient/gui/SearchBar/styles/index.js
|
||||
@@ -169,12 +203,24 @@ ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
ElectronClient/gui/ToolbarBase.js
|
||||
ElectronClient/gui/ToolbarButton/styles/index.js
|
||||
ElectronClient/gui/ToolbarButton/ToolbarButton.js
|
||||
ElectronClient/gui/utils/NoteListUtils.js
|
||||
ElectronClient/InteropServiceHelper.js
|
||||
ElectronClient/services/bridge.js
|
||||
ElectronClient/services/plugins/hooks/useThemeCss.js
|
||||
ElectronClient/services/plugins/hooks/useViewIsReady.js
|
||||
ElectronClient/services/plugins/PlatformImplementation.js
|
||||
ElectronClient/services/plugins/PluginRunner.js
|
||||
ElectronClient/services/plugins/UserWebview.js
|
||||
ElectronClient/services/plugins/UserWebviewDialog.js
|
||||
ElectronClient/services/plugins/UserWebviewDialogButtonBar.js
|
||||
ReactNativeClient/lib/AsyncActionQueue.js
|
||||
ReactNativeClient/lib/BaseApplication.js
|
||||
ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
ReactNativeClient/lib/hooks/useEffectDebugger.js
|
||||
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
|
||||
ReactNativeClient/lib/hooks/usePrevious.js
|
||||
@@ -184,15 +230,74 @@ ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
|
||||
ReactNativeClient/lib/JoplinServerApi.js
|
||||
ReactNativeClient/lib/locale.js
|
||||
ReactNativeClient/lib/Logger.js
|
||||
ReactNativeClient/lib/models/Alarm.js
|
||||
ReactNativeClient/lib/models/Setting.js
|
||||
ReactNativeClient/lib/ntpDate.js
|
||||
ReactNativeClient/lib/reducer.js
|
||||
ReactNativeClient/lib/services/AlarmService.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.ios.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriverNode.js
|
||||
ReactNativeClient/lib/services/BaseService.js
|
||||
ReactNativeClient/lib/services/BooleanExpression.js
|
||||
ReactNativeClient/lib/services/commands/MenuUtils.js
|
||||
ReactNativeClient/lib/services/commands/propsHaveChanged.js
|
||||
ReactNativeClient/lib/services/commands/ToolbarButtonUtils.js
|
||||
ReactNativeClient/lib/services/CommandService.js
|
||||
ReactNativeClient/lib/services/contextkey/contextkey.js
|
||||
ReactNativeClient/lib/services/debug/populateDatabase.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Html.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService.js
|
||||
ReactNativeClient/lib/services/interop/types.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainService.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.mobile.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.node.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriverBase.js
|
||||
ReactNativeClient/lib/services/KeymapService.js
|
||||
ReactNativeClient/lib/services/plugins/api/Global.js
|
||||
ReactNativeClient/lib/services/plugins/api/Joplin.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinCommands.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinData.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinFilters.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinInterop.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinPlugins.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinUtils.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
|
||||
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
|
||||
ReactNativeClient/lib/services/plugins/MenuItemController.js
|
||||
ReactNativeClient/lib/services/plugins/Plugin.js
|
||||
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/createViewHandle.js
|
||||
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
|
||||
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js
|
||||
ReactNativeClient/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
ReactNativeClient/lib/services/plugins/utils/types.js
|
||||
ReactNativeClient/lib/services/plugins/ViewController.js
|
||||
ReactNativeClient/lib/services/plugins/WebviewController.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/index.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/reducer.js
|
||||
ReactNativeClient/lib/services/rest/actionApi.desktop.js
|
||||
@@ -209,6 +314,8 @@ ReactNativeClient/lib/services/synchronizer/utils/types.js
|
||||
ReactNativeClient/lib/services/UndoRedoService.js
|
||||
ReactNativeClient/lib/ShareExtension.js
|
||||
ReactNativeClient/lib/shareHandler.js
|
||||
ReactNativeClient/lib/shim.js
|
||||
ReactNativeClient/lib/Synchronizer.js
|
||||
ReactNativeClient/lib/theme.js
|
||||
ReactNativeClient/lib/themes/aritimDark.js
|
||||
ReactNativeClient/lib/themes/dark.js
|
||||
@@ -219,6 +326,7 @@ ReactNativeClient/lib/themes/oledDark.js
|
||||
ReactNativeClient/lib/themes/solarizedDark.js
|
||||
ReactNativeClient/lib/themes/solarizedLight.js
|
||||
ReactNativeClient/lib/themes/type.js
|
||||
ReactNativeClient/lib/uuid.js
|
||||
ReactNativeClient/lib/versionInfo.js
|
||||
ReactNativeClient/PluginAssetsLoader.js
|
||||
ReactNativeClient/setUpQuickActions.js
|
||||
|
16
.eslintrc.js
16
.eslintrc.js
@@ -48,8 +48,9 @@ module.exports = {
|
||||
// -------------------------------
|
||||
'react/jsx-uses-react': 'error',
|
||||
'react/jsx-uses-vars': 'error',
|
||||
'no-unused-vars': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'error',
|
||||
'no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }],
|
||||
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||
'no-constant-condition': 0,
|
||||
'no-prototype-builtins': 0,
|
||||
// This error is always a false positive so far since it detects
|
||||
@@ -121,4 +122,15 @@ module.exports = {
|
||||
'react-hooks',
|
||||
'import',
|
||||
],
|
||||
'overrides': [
|
||||
{
|
||||
// enable the rule specifically for TypeScript files
|
||||
'files': ['*.ts', '*.tsx'],
|
||||
'rules': {
|
||||
// Warn only because it would make it difficult to convert JS classes to TypeScript, unless we
|
||||
// make everything public which is not great. New code however should specify member accessibility.
|
||||
'@typescript-eslint/explicit-member-accessibility': ['warn'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
112
.gitignore
vendored
112
.gitignore
vendored
@@ -52,15 +52,47 @@ Tools/commit_hook.txt
|
||||
*.map
|
||||
ReactNativeClient/lib/sql-extensions/spellfix.so
|
||||
ReactNativeClient/lib/sql-extensions/spellfix.dylib
|
||||
CliClient/build/
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
CliClient/app/LinkSelector.js
|
||||
CliClient/build/LinkSelector.js
|
||||
CliClient/app/services/plugins/PluginRunner.js
|
||||
CliClient/tests/models_Setting.js
|
||||
CliClient/tests/services_CommandService.js
|
||||
CliClient/tests/services_InteropService.js
|
||||
CliClient/tests/services_PluginService.js
|
||||
CliClient/tests/services/plugins/sandboxProxy.js
|
||||
CliClient/tests/support/plugins/codemirror_test/global.d.js
|
||||
CliClient/tests/support/plugins/codemirror_test/src/index.js
|
||||
CliClient/tests/support/plugins/dialog/global.d.js
|
||||
CliClient/tests/support/plugins/dialog/src/index.js
|
||||
CliClient/tests/support/plugins/events/global.d.js
|
||||
CliClient/tests/support/plugins/events/src/index.js
|
||||
CliClient/tests/support/plugins/json_export/global.d.js
|
||||
CliClient/tests/support/plugins/json_export/src/index.js
|
||||
CliClient/tests/support/plugins/markdown_plugin/global.d.js
|
||||
CliClient/tests/support/plugins/markdown_plugin/src/index.js
|
||||
CliClient/tests/support/plugins/multi_selection/global.d.js
|
||||
CliClient/tests/support/plugins/multi_selection/src/index.js
|
||||
CliClient/tests/support/plugins/register_command/global.d.js
|
||||
CliClient/tests/support/plugins/register_command/src/index.js
|
||||
CliClient/tests/support/plugins/selected_text/global.d.js
|
||||
CliClient/tests/support/plugins/selected_text/src/index.js
|
||||
CliClient/tests/support/plugins/settings/global.d.js
|
||||
CliClient/tests/support/plugins/settings/src/index.js
|
||||
CliClient/tests/support/plugins/toc/global.d.js
|
||||
CliClient/tests/support/plugins/toc/src/index.js
|
||||
CliClient/tests/support/plugins/withExternalModules/global.d.js
|
||||
CliClient/tests/support/plugins/withExternalModules/src/index.js
|
||||
CliClient/tests/synchronizer_LockHandler.js
|
||||
CliClient/tests/synchronizer_MigrationHandler.js
|
||||
ElectronClient/app.js
|
||||
ElectronClient/bridge.js
|
||||
ElectronClient/commands/copyDevCommand.js
|
||||
ElectronClient/commands/focusElement.js
|
||||
ElectronClient/commands/startExternalEditing.js
|
||||
ElectronClient/commands/stopExternalEditing.js
|
||||
ElectronClient/ElectronAppWrapper.js
|
||||
ElectronClient/global.d.js
|
||||
ElectronClient/gui/Button/Button.js
|
||||
ElectronClient/gui/ConfigScreen/ButtonBar.js
|
||||
@@ -96,6 +128,7 @@ ElectronClient/gui/MainScreen/commands/toggleNoteList.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleSidebar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
@@ -131,7 +164,7 @@ ElectronClient/gui/NoteEditor/utils/useFormNote.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteToolbarButtons.js
|
||||
ElectronClient/gui/NoteEditor/utils/usePluginServiceRegistration.js
|
||||
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
|
||||
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
|
||||
@@ -147,6 +180,7 @@ ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
ElectronClient/gui/ResizableLayout/ResizableLayout.js
|
||||
ElectronClient/gui/ResourceScreen.js
|
||||
ElectronClient/gui/Root_UpgradeSyncTarget.js
|
||||
ElectronClient/gui/Root.js
|
||||
ElectronClient/gui/SearchBar/hooks/useSearch.js
|
||||
ElectronClient/gui/SearchBar/SearchBar.js
|
||||
ElectronClient/gui/SearchBar/styles/index.js
|
||||
@@ -162,12 +196,24 @@ ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
ElectronClient/gui/ToolbarBase.js
|
||||
ElectronClient/gui/ToolbarButton/styles/index.js
|
||||
ElectronClient/gui/ToolbarButton/ToolbarButton.js
|
||||
ElectronClient/gui/utils/NoteListUtils.js
|
||||
ElectronClient/InteropServiceHelper.js
|
||||
ElectronClient/services/bridge.js
|
||||
ElectronClient/services/plugins/hooks/useThemeCss.js
|
||||
ElectronClient/services/plugins/hooks/useViewIsReady.js
|
||||
ElectronClient/services/plugins/PlatformImplementation.js
|
||||
ElectronClient/services/plugins/PluginRunner.js
|
||||
ElectronClient/services/plugins/UserWebview.js
|
||||
ElectronClient/services/plugins/UserWebviewDialog.js
|
||||
ElectronClient/services/plugins/UserWebviewDialogButtonBar.js
|
||||
ReactNativeClient/lib/AsyncActionQueue.js
|
||||
ReactNativeClient/lib/BaseApplication.js
|
||||
ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
ReactNativeClient/lib/hooks/useEffectDebugger.js
|
||||
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
|
||||
ReactNativeClient/lib/hooks/usePrevious.js
|
||||
@@ -177,15 +223,74 @@ ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
|
||||
ReactNativeClient/lib/JoplinServerApi.js
|
||||
ReactNativeClient/lib/locale.js
|
||||
ReactNativeClient/lib/Logger.js
|
||||
ReactNativeClient/lib/models/Alarm.js
|
||||
ReactNativeClient/lib/models/Setting.js
|
||||
ReactNativeClient/lib/ntpDate.js
|
||||
ReactNativeClient/lib/reducer.js
|
||||
ReactNativeClient/lib/services/AlarmService.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.ios.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriverNode.js
|
||||
ReactNativeClient/lib/services/BaseService.js
|
||||
ReactNativeClient/lib/services/BooleanExpression.js
|
||||
ReactNativeClient/lib/services/commands/MenuUtils.js
|
||||
ReactNativeClient/lib/services/commands/propsHaveChanged.js
|
||||
ReactNativeClient/lib/services/commands/ToolbarButtonUtils.js
|
||||
ReactNativeClient/lib/services/CommandService.js
|
||||
ReactNativeClient/lib/services/contextkey/contextkey.js
|
||||
ReactNativeClient/lib/services/debug/populateDatabase.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Html.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService.js
|
||||
ReactNativeClient/lib/services/interop/types.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainService.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.mobile.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.node.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriverBase.js
|
||||
ReactNativeClient/lib/services/KeymapService.js
|
||||
ReactNativeClient/lib/services/plugins/api/Global.js
|
||||
ReactNativeClient/lib/services/plugins/api/Joplin.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinCommands.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinData.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinFilters.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinInterop.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinPlugins.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinUtils.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
|
||||
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
|
||||
ReactNativeClient/lib/services/plugins/MenuItemController.js
|
||||
ReactNativeClient/lib/services/plugins/Plugin.js
|
||||
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/createViewHandle.js
|
||||
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
|
||||
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js
|
||||
ReactNativeClient/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
ReactNativeClient/lib/services/plugins/utils/types.js
|
||||
ReactNativeClient/lib/services/plugins/ViewController.js
|
||||
ReactNativeClient/lib/services/plugins/WebviewController.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/index.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/reducer.js
|
||||
ReactNativeClient/lib/services/rest/actionApi.desktop.js
|
||||
@@ -202,6 +307,8 @@ ReactNativeClient/lib/services/synchronizer/utils/types.js
|
||||
ReactNativeClient/lib/services/UndoRedoService.js
|
||||
ReactNativeClient/lib/ShareExtension.js
|
||||
ReactNativeClient/lib/shareHandler.js
|
||||
ReactNativeClient/lib/shim.js
|
||||
ReactNativeClient/lib/Synchronizer.js
|
||||
ReactNativeClient/lib/theme.js
|
||||
ReactNativeClient/lib/themes/aritimDark.js
|
||||
ReactNativeClient/lib/themes/dark.js
|
||||
@@ -212,6 +319,7 @@ ReactNativeClient/lib/themes/oledDark.js
|
||||
ReactNativeClient/lib/themes/solarizedDark.js
|
||||
ReactNativeClient/lib/themes/solarizedLight.js
|
||||
ReactNativeClient/lib/themes/type.js
|
||||
ReactNativeClient/lib/uuid.js
|
||||
ReactNativeClient/lib/versionInfo.js
|
||||
ReactNativeClient/PluginAssetsLoader.js
|
||||
ReactNativeClient/setUpQuickActions.js
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { netUtils } = require('lib/net-utils.js');
|
||||
|
||||
const http = require('http');
|
||||
|
@@ -1,15 +1,17 @@
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { reducer, defaultState } = require('lib/reducer.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const reducer = require('lib/reducer').default;
|
||||
const { defaultState } = require('lib/reducer');
|
||||
const { splitCommandString } = require('lib/string-utils.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const shim = require('lib/shim').default;
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = new Entities().encode;
|
||||
|
||||
@@ -477,7 +479,7 @@ class AppGui {
|
||||
this.linkSelector_.noteX + cursorOffsetX,
|
||||
this.linkSelector_.noteY + cursorOffsetY
|
||||
);
|
||||
setTimeout(() => this.term_.term().inverse(this.linkSelector_.link), 50);
|
||||
shim.setTimeout(() => this.term_.term().inverse(this.linkSelector_.link), 50);
|
||||
}
|
||||
} else if (cmd === 'open_link') {
|
||||
if (this.widget('noteText').hasFocus) {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const { BaseApplication } = require('lib/BaseApplication');
|
||||
const BaseApplication = require('lib/BaseApplication').default;
|
||||
const { FoldersScreenUtils } = require('lib/folders-screen-utils.js');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
@@ -6,14 +6,15 @@ const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { fileExtension } = require('lib/path-utils.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const fs = require('fs-extra');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const Cache = require('lib/Cache');
|
||||
const RevisionService = require('lib/services/RevisionService');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
class Application extends BaseApplication {
|
||||
constructor() {
|
||||
@@ -161,7 +162,7 @@ class Application extends BaseApplication {
|
||||
};
|
||||
|
||||
// Give it a few seconds to cancel otherwise exit anyway
|
||||
setTimeout(async () => {
|
||||
shim.setTimeout(async () => {
|
||||
await doExit();
|
||||
}, 5000);
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { reg } = require('lib/registry.js');
|
||||
|
||||
class BaseCommand {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const fs = require('fs-extra');
|
||||
const { fileExtension, dirname } = require('lib/path-utils.js');
|
||||
const wrap_ = require('word-wrap');
|
||||
const { languageCode } = require('lib/locale.js');
|
||||
const { languageCode } = require('lib/locale');
|
||||
|
||||
const rootDir = dirname(dirname(__dirname));
|
||||
const MAX_WIDTH = 78;
|
||||
|
@@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { dirname } = require('lib/path-utils.js');
|
||||
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
|
||||
const { JoplinDatabase } = require('lib/joplin-database.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const yargParser = require('yargs-parser');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const stringPadding = require('string-padding');
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
|
||||
const cliUtils = {};
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _, setLocale } = require('lib/locale.js');
|
||||
const { _, setLocale } = require('lib/locale');
|
||||
const { app } = require('./app.js');
|
||||
const fs = require('fs-extra');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
@@ -1,10 +1,10 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
const DecryptionWorker = require('lib/services/DecryptionWorker');
|
||||
const BaseItem = require('lib/models/BaseItem');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const shim = require('lib/shim').default;
|
||||
const pathUtils = require('lib/path-utils.js');
|
||||
const imageType = require('image-type');
|
||||
const readChunk = require('read-chunk');
|
||||
@@ -38,7 +38,7 @@ class Command extends BaseCommand {
|
||||
this.stdout(_('Operation cancelled'));
|
||||
return false;
|
||||
}
|
||||
Setting.setObjectKey('encryption.passwordCache', masterKeyId, password);
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKeyId, password);
|
||||
await EncryptionService.instance().loadMasterKeysFromSettings();
|
||||
return true;
|
||||
};
|
||||
|
@@ -1,11 +1,11 @@
|
||||
const fs = require('fs-extra');
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { splitCommandString } = require('lib/string-utils.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const uuid = require('lib/uuid').default;
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { ReportService } = require('lib/services/report.js');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const InteropService = require('lib/services/interop/InteropService').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -14,7 +14,7 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
options() {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const formats = service
|
||||
.modules()
|
||||
.filter(m => m.type === 'exporter' && m.format !== 'html')
|
||||
@@ -41,7 +41,7 @@ class Command extends BaseCommand {
|
||||
exportOptions.sourceFolderIds = folders.map(n => n.id);
|
||||
}
|
||||
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const result = await service.export(exportOptions);
|
||||
|
||||
result.warnings.map(w => this.stdout(w));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { renderCommandHelp } = require('./help-utils.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const InteropService = require('lib/services/interop/InteropService').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -15,7 +15,7 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
options() {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const formats = service
|
||||
.modules()
|
||||
.filter(m => m.type === 'importer')
|
||||
@@ -63,7 +63,7 @@ class Command extends BaseCommand {
|
||||
|
||||
app().gui().showConsole();
|
||||
this.stdout(_('Importing notes...'));
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const result = await service.import(importOptions);
|
||||
result.warnings.map(w => this.stdout(w));
|
||||
cliUtils.redrawDone();
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const uuid = require('lib/uuid').default;
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const { _ } = require('lib/locale');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Logger = require('lib/Logger').default;
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale');
|
||||
const { ReportService } = require('lib/services/report.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { OneDriveApiNodeUtils } = require('lib/onedrive-api-node-utils.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const ResourceFetcher = require('lib/services/ResourceFetcher');
|
||||
const { Synchronizer } = require('lib/synchronizer.js');
|
||||
const Synchronizer = require('lib/Synchronizer').default;
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const md5 = require('md5');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
const CommandDone = require('./command-done.js');
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { Logger } = require('lib/logger.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');
|
||||
|
@@ -2,7 +2,7 @@ const Folder = require('lib/models/Folder.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const ListWidget = require('tkwidgets/ListWidget.js');
|
||||
const _ = require('lib/locale.js')._;
|
||||
const _ = require('lib/locale')._;
|
||||
|
||||
class FolderListWidget extends ListWidget {
|
||||
constructor() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const Note = require('lib/models/Note.js');
|
||||
const TextWidget = require('tkwidgets/TextWidget.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
class NoteWidget extends TextWidget {
|
||||
constructor() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { wrap } = require('lib/string-utils.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale');
|
||||
|
||||
const MAX_WIDTH = 78;
|
||||
const INDENT = ' ';
|
||||
|
@@ -21,12 +21,12 @@ const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const NoteTag = require('lib/models/NoteTag.js');
|
||||
const MasterKey = require('lib/models/MasterKey');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Revision = require('lib/models/Revision.js');
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
||||
const { shimInit } = require('lib/shim-init-node.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { FileApiDriverLocal } = require('lib/file-api-driver-local.js');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
const envFromArgs = require('lib/envFromArgs');
|
||||
|
68
CliClient/app/services/plugins/PluginRunner.ts
Normal file
68
CliClient/app/services/plugins/PluginRunner.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import * as vm from 'vm';
|
||||
import Plugin from 'lib/services/plugins/Plugin';
|
||||
import sandboxProxy from 'lib/services/plugins/sandboxProxy';
|
||||
import BasePluginRunner from 'lib/services/plugins/BasePluginRunner';
|
||||
import executeSandboxCall from 'lib/services/plugins/utils/executeSandboxCall';
|
||||
import Global from 'lib/services/plugins/api/Global';
|
||||
import mapEventHandlersToIds, { EventHandlers } from 'lib/services/plugins/utils/mapEventHandlersToIds';
|
||||
|
||||
function createConsoleWrapper(pluginId:string) {
|
||||
const wrapper:any = {};
|
||||
|
||||
for (const n in console) {
|
||||
if (!console.hasOwnProperty(n)) continue;
|
||||
wrapper[n] = (...args:any[]) => {
|
||||
const newArgs = args.slice();
|
||||
newArgs.splice(0, 0, `Plugin "${pluginId}":`);
|
||||
return (console as any)[n](...newArgs);
|
||||
};
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// The CLI plugin runner is more complex than it needs to be because it more or less emulates
|
||||
// how it would work in a multi-process architecture, as in the desktop app (and probably how
|
||||
// it would work in the mobile app too). This is mainly to allow doing integration testing.
|
||||
//
|
||||
// For example, all plugin calls go through a proxy, however they could made directly since
|
||||
// the plugin script is running within the same process as the main app.
|
||||
|
||||
export default class PluginRunner extends BasePluginRunner {
|
||||
|
||||
private eventHandlers_:EventHandlers = {};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.eventHandler = this.eventHandler.bind(this);
|
||||
}
|
||||
|
||||
private async eventHandler(eventHandlerId:string, args:any[]) {
|
||||
const cb = this.eventHandlers_[eventHandlerId];
|
||||
return cb(...args);
|
||||
}
|
||||
|
||||
private newSandboxProxy(pluginId:string, sandbox:Global) {
|
||||
const target = async (path:string, args:any[]) => {
|
||||
return executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
|
||||
};
|
||||
|
||||
return {
|
||||
joplin: sandboxProxy(target),
|
||||
console: createConsoleWrapper(pluginId),
|
||||
};
|
||||
}
|
||||
|
||||
async run(plugin:Plugin, sandbox:Global) {
|
||||
const vmSandbox = vm.createContext(this.newSandboxProxy(plugin.id, sandbox));
|
||||
|
||||
try {
|
||||
vm.runInContext(plugin.scriptText, vmSandbox);
|
||||
} catch (error) {
|
||||
this.logger().error(`In plugin ${plugin.id}:`, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -46,8 +46,14 @@ tasks.prepareTestBuild = {
|
||||
],
|
||||
});
|
||||
|
||||
await utils.copyDir(`${__dirname}/../ReactNativeClient/lib`, `${testBuildDir}/lib`);
|
||||
await utils.copyDir(`${__dirname}/../ReactNativeClient/locales`, `${testBuildDir}/locales`);
|
||||
const rootDir = utils.rootDir();
|
||||
|
||||
await utils.copyDir(`${rootDir}/ReactNativeClient/lib`, `${testBuildDir}/lib`, {
|
||||
excluded: [
|
||||
`${rootDir}/ReactNativeClient/lib/joplin-renderer/node_modules`,
|
||||
],
|
||||
});
|
||||
await utils.copyDir(`${rootDir}/ReactNativeClient/locales`, `${testBuildDir}/locales`);
|
||||
await fs.mkdirp(`${testBuildDir}/data`);
|
||||
},
|
||||
};
|
||||
|
20
CliClient/package-lock.json
generated
20
CliClient/package-lock.json
generated
@@ -606,6 +606,11 @@
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
||||
"dev": true
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz",
|
||||
"integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw=="
|
||||
},
|
||||
"cache-base": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
|
||||
@@ -4344,6 +4349,11 @@
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
|
||||
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.12",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz",
|
||||
"integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A=="
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||
@@ -5250,6 +5260,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"re-reselect": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/re-reselect/-/re-reselect-4.0.0.tgz",
|
||||
"integrity": "sha512-wuygyq8TXUlSdVXv2kigXxQNOgdb9m7LbIjwfTNGSpaY1riLd5e+VeQjlQMyUtrk0oiyhi1AqIVynworl3qxHA=="
|
||||
},
|
||||
"read-chunk": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz",
|
||||
@@ -5610,6 +5625,11 @@
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
|
||||
},
|
||||
"reselect": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz",
|
||||
"integrity": "sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
|
||||
|
@@ -28,7 +28,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.2.2",
|
||||
"version": "1.3.0",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
@@ -41,6 +41,7 @@
|
||||
"aws-sdk": "^2.588.0",
|
||||
"base-64": "^0.1.0",
|
||||
"base64-stream": "^1.0.0",
|
||||
"builtin-modules": "^3.1.0",
|
||||
"clean-html": "^1.5.0",
|
||||
"compare-version": "^0.1.2",
|
||||
"diacritics": "^1.3.0",
|
||||
@@ -83,6 +84,7 @@
|
||||
"mime": "^2.0.3",
|
||||
"moment": "^2.24.0",
|
||||
"multiparty": "^4.2.1",
|
||||
"nanoid": "^3.1.12",
|
||||
"node-emoji": "^1.8.1",
|
||||
"node-fetch": "^1.7.1",
|
||||
"node-persist": "^2.1.0",
|
||||
@@ -91,13 +93,16 @@
|
||||
"promise": "^7.1.1",
|
||||
"proper-lockfile": "^2.0.1",
|
||||
"query-string": "4.3.4",
|
||||
"re-reselect": "^4.0.0",
|
||||
"read-chunk": "^2.1.0",
|
||||
"redux": "^3.7.2",
|
||||
"relative": "^3.0.2",
|
||||
"request": "^2.88.0",
|
||||
"reselect": "^4.0.0",
|
||||
"sax": "^1.2.4",
|
||||
"server-destroy": "^1.0.1",
|
||||
"sharp": "^0.23.2",
|
||||
"slug": "^3.3.4",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"sqlite3": "^4.1.1",
|
||||
"string-padding": "^1.0.2",
|
||||
@@ -109,7 +114,6 @@
|
||||
"terminal-kit": "^1.30.0",
|
||||
"tkwidgets": "^0.5.26",
|
||||
"url-parse": "^1.4.7",
|
||||
"slug": "^3.3.4",
|
||||
"uuid": "^3.0.1",
|
||||
"valid-url": "^1.0.9",
|
||||
"word-wrap": "^1.2.3",
|
||||
|
@@ -1,7 +1,7 @@
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
const { enexXmlToHtml } = require('lib/import-enex-html-gen.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
|
@@ -9,7 +9,7 @@ const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
|
@@ -9,7 +9,7 @@ const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
const HtmlToHtml = require('lib/joplin-renderer/HtmlToHtml');
|
||||
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
|
||||
|
||||
|
@@ -9,7 +9,7 @@ const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
const HtmlToMd = require('lib/HtmlToMd');
|
||||
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
|
||||
|
||||
|
@@ -9,7 +9,7 @@ const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
const MdToHtml = require('lib/joplin-renderer/MdToHtml');
|
||||
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
|
||||
const { themeStyle } = require('lib/theme');
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const mdImporterService = require('lib/services/InteropService_Importer_Md');
|
||||
const mdImporterService = require('lib/services/interop/InteropService_Importer_Md').default;
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
|
||||
|
||||
|
@@ -6,10 +6,10 @@ const { time } = require('lib/time-utils.js');
|
||||
const { sortedIds, createNTestNotes, 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 Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const ArrayUtils = require('lib/ArrayUtils.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
121
CliClient/tests/eventManager.js
Normal file
121
CliClient/tests/eventManager.js
Normal file
@@ -0,0 +1,121 @@
|
||||
'use strict';
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { asyncTest,checkThrow } = require('test-utils.js');
|
||||
const eventManager = require('lib/eventManager').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('eventManager', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
eventManager.reset();
|
||||
done();
|
||||
});
|
||||
|
||||
afterEach(async (done) => {
|
||||
eventManager.reset();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should watch state props', asyncTest(async () => {
|
||||
let localStateName = '';
|
||||
let callCount = 0;
|
||||
|
||||
function nameWatch(event) {
|
||||
callCount++;
|
||||
localStateName = event.value;
|
||||
}
|
||||
|
||||
const globalState = {
|
||||
name: 'john',
|
||||
};
|
||||
|
||||
eventManager.appStateOn('name', nameWatch);
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(localStateName).toBe('john');
|
||||
|
||||
globalState.name = 'paul';
|
||||
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(localStateName).toBe('paul');
|
||||
|
||||
expect(callCount).toBe(2);
|
||||
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(callCount).toBe(2);
|
||||
}));
|
||||
|
||||
it('should unwatch state props', asyncTest(async () => {
|
||||
let localStateName = '';
|
||||
|
||||
function nameWatch(event) {
|
||||
localStateName = event.value;
|
||||
}
|
||||
|
||||
const globalState = {
|
||||
name: 'john',
|
||||
};
|
||||
|
||||
eventManager.appStateOn('name', nameWatch);
|
||||
eventManager.appStateOff('name', nameWatch);
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(localStateName).toBe('');
|
||||
}));
|
||||
|
||||
it('should watch nested props', asyncTest(async () => {
|
||||
let localStateName = '';
|
||||
|
||||
function nameWatch(event) {
|
||||
localStateName = event.value;
|
||||
}
|
||||
|
||||
const globalState = {
|
||||
user: {
|
||||
name: 'john',
|
||||
},
|
||||
};
|
||||
|
||||
eventManager.appStateOn('user.name', nameWatch);
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(localStateName).toBe('john');
|
||||
|
||||
globalState.user.name = 'paul';
|
||||
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(localStateName).toBe('paul');
|
||||
}));
|
||||
|
||||
it('should not be possible to modify state props', asyncTest(async () => {
|
||||
let localUser = {};
|
||||
|
||||
function userWatch(event) {
|
||||
// Normally, the user should not keep a reference to the whole object
|
||||
// but make a copy. However, if they do keep a reference and try to
|
||||
// modify it, it should throw an exception as that would be an attempt
|
||||
// to directly modify the Redux state.
|
||||
localUser = event.value;
|
||||
}
|
||||
|
||||
const globalState = {
|
||||
user: {
|
||||
name: 'john',
|
||||
},
|
||||
};
|
||||
|
||||
eventManager.appStateOn('user', userWatch);
|
||||
eventManager.appStateEmit(globalState);
|
||||
|
||||
expect(checkThrow(() => localUser.name = 'paul')).toBe(true);
|
||||
}));
|
||||
|
||||
});
|
@@ -1,7 +1,7 @@
|
||||
require('app-module-path').addPath(__dirname);
|
||||
const { asyncTest, id, ids, createNTestFolders, sortedIds, createNTestNotes, TestApp } = require('test-utils.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const uuid = require('lib/uuid').default;
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
require('app-module-path').addPath(__dirname);
|
||||
const { setupDatabaseAndSynchronizer, switchClient, asyncTest, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('test-utils.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
require('app-module-path').addPath(__dirname);
|
||||
const { setupDatabaseAndSynchronizer, switchClient, asyncTest, id, ids, sortedIds, at, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('test-utils.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
require('app-module-path').addPath(__dirname);
|
||||
const { setupDatabaseAndSynchronizer, switchClient, asyncTest, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('test-utils.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
|
@@ -2,12 +2,12 @@
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const uuid = require('lib/uuid').default;
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { asyncTest, sleep, fileApi, fileContentEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const shim = require('lib/shim').default;
|
||||
const fs = require('fs-extra');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -9,7 +9,7 @@ const Note = require('lib/models/Note.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -7,7 +7,7 @@ const { createNTestNotes, asyncTest, fileContentEqual, setupDatabase, setupDatab
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -8,7 +8,7 @@ const SearchEngine = require('lib/services/searchengine/SearchEngine');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
const ItemChangeUtils = require('lib/services/ItemChangeUtils');
|
||||
const Note = require('lib/models/Note');
|
||||
const Setting = require('lib/models/Setting');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const ItemChange = require('lib/models/ItemChange');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
|
@@ -6,10 +6,10 @@ const { time } = require('lib/time-utils.js');
|
||||
const { sortedIds, createNTestNotes, 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 Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const ArrayUtils = require('lib/ArrayUtils.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -6,10 +6,10 @@ const { time } = require('lib/time-utils.js');
|
||||
const { sortedIds, createNTestNotes, 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 Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const ArrayUtils = require('lib/ArrayUtils.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -8,7 +8,7 @@ const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -10,7 +10,7 @@ const NoteTag = require('lib/models/NoteTag.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const Revision = require('lib/models/Revision.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -1,37 +0,0 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('models_Setting', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return only sub-values', asyncTest(async () => {
|
||||
const settings = {
|
||||
'sync.5.path': 'http://example.com',
|
||||
'sync.5.username': 'testing',
|
||||
};
|
||||
|
||||
let output = Setting.subValues('sync.5', settings);
|
||||
expect(output['path']).toBe('http://example.com');
|
||||
expect(output['username']).toBe('testing');
|
||||
|
||||
output = Setting.subValues('sync.4', settings);
|
||||
expect('path' in output).toBe(false);
|
||||
expect('username' in output).toBe(false);
|
||||
}));
|
||||
|
||||
});
|
135
CliClient/tests/models_Setting.ts
Normal file
135
CliClient/tests/models_Setting.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import Setting from 'lib/models/Setting';
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('test-utils.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('models_Setting', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should return only sub-values', asyncTest(async () => {
|
||||
const settings = {
|
||||
'sync.5.path': 'http://example.com',
|
||||
'sync.5.username': 'testing',
|
||||
};
|
||||
|
||||
let output = Setting.subValues('sync.5', settings);
|
||||
expect(output['path']).toBe('http://example.com');
|
||||
expect(output['username']).toBe('testing');
|
||||
|
||||
output = Setting.subValues('sync.4', settings);
|
||||
expect('path' in output).toBe(false);
|
||||
expect('username' in output).toBe(false);
|
||||
}));
|
||||
|
||||
it('should allow registering new settings dynamically', asyncTest(async () => {
|
||||
await expectThrow(async () => Setting.setValue('myCustom', '123'));
|
||||
|
||||
await Setting.registerSetting('myCustom', {
|
||||
public: true,
|
||||
value: 'default',
|
||||
type: Setting.TYPE_STRING,
|
||||
});
|
||||
|
||||
await expectNotThrow(async () => Setting.setValue('myCustom', '123'));
|
||||
|
||||
expect(Setting.value('myCustom')).toBe('123');
|
||||
}));
|
||||
|
||||
it('should not clear old custom settings', asyncTest(async () => {
|
||||
// In general the following should work:
|
||||
//
|
||||
// - Plugin register a new setting
|
||||
// - User set new value for setting
|
||||
// - Settings are saved
|
||||
// - => App restart
|
||||
// - Plugin does not register setting again
|
||||
// - Settings are loaded
|
||||
// - Settings are saved
|
||||
// - Plugin register setting again
|
||||
// - Previous value set by user should still be there.
|
||||
//
|
||||
// In other words, once a custom setting has been set we don't clear it
|
||||
// even if registration doesn't happen immediately. That allows for example
|
||||
// to delay setting registration without a risk for the custom setting to be deleted.
|
||||
|
||||
await Setting.registerSetting('myCustom', {
|
||||
public: true,
|
||||
value: 'default',
|
||||
type: Setting.TYPE_STRING,
|
||||
});
|
||||
|
||||
Setting.setValue('myCustom', '123');
|
||||
|
||||
await Setting.saveAll();
|
||||
|
||||
await Setting.reset();
|
||||
|
||||
await Setting.load();
|
||||
|
||||
await Setting.registerSetting('myCustom', {
|
||||
public: true,
|
||||
value: 'default',
|
||||
type: Setting.TYPE_STRING,
|
||||
});
|
||||
|
||||
await Setting.saveAll();
|
||||
|
||||
expect(Setting.value('myCustom')).toBe('123');
|
||||
}));
|
||||
|
||||
it('should return values with correct type for custom settings', asyncTest(async () => {
|
||||
await Setting.registerSetting('myCustom', {
|
||||
public: true,
|
||||
value: 123,
|
||||
type: Setting.TYPE_INT,
|
||||
});
|
||||
|
||||
Setting.setValue('myCustom', 456);
|
||||
|
||||
await Setting.saveAll();
|
||||
await Setting.reset();
|
||||
await Setting.load();
|
||||
|
||||
await Setting.registerSetting('myCustom', {
|
||||
public: true,
|
||||
value: 123,
|
||||
type: Setting.TYPE_INT,
|
||||
});
|
||||
|
||||
expect(typeof Setting.value('myCustom')).toBe('number');
|
||||
expect(Setting.value('myCustom')).toBe(456);
|
||||
}));
|
||||
|
||||
it('should validate registered keys', asyncTest(async () => {
|
||||
const md = {
|
||||
public: true,
|
||||
value: 'default',
|
||||
type: Setting.TYPE_STRING,
|
||||
};
|
||||
|
||||
await expectThrow(async () => await Setting.registerSetting('', md));
|
||||
await expectThrow(async () => await Setting.registerSetting('no spaces', md));
|
||||
await expectThrow(async () => await Setting.registerSetting('nospecialcharacters!!!', md));
|
||||
await expectThrow(async () => await Setting.registerSetting('Robert\'); DROP TABLE Students;--', md));
|
||||
|
||||
await expectNotThrow(async () => await Setting.registerSetting('numbersareok123', md));
|
||||
await expectNotThrow(async () => await Setting.registerSetting('so-ARE-dashes_123', md));
|
||||
}));
|
||||
|
||||
it('should register new sections', asyncTest(async () => {
|
||||
await Setting.registerSection('mySection', {
|
||||
label: 'My section',
|
||||
});
|
||||
|
||||
expect(Setting.sectionNameToLabel('mySection')).toBe('My section');
|
||||
}));
|
||||
});
|
@@ -9,7 +9,7 @@ const Note = require('lib/models/Note.js');
|
||||
const NoteTag = require('lib/models/NoteTag.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -5,7 +5,8 @@ const { setupDatabaseAndSynchronizer, switchClient, asyncTest, createNTestNotes,
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const { reducer, defaultState, stateUtils, MAX_HISTORY } = require('lib/reducer.js');
|
||||
const reducer = require('lib/reducer').default;
|
||||
const { defaultState, stateUtils, MAX_HISTORY } = require('lib/reducer');
|
||||
|
||||
function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags = null, selectedTagIndex = null) {
|
||||
let state = defaultState;
|
||||
@@ -87,7 +88,7 @@ function getIds(items, indexes = null) {
|
||||
|
||||
let insideBeforeEach = false;
|
||||
|
||||
describe('Reducer', function() {
|
||||
describe('reducer', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
insideBeforeEach = true;
|
||||
|
58
CliClient/tests/services/plugins/sandboxProxy.ts
Normal file
58
CliClient/tests/services/plugins/sandboxProxy.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import sandboxProxy, { Target } from 'lib/services/plugins/sandboxProxy';
|
||||
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
|
||||
|
||||
describe('services_plugins_sandboxProxy', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should create a new sandbox proxy', asyncTest(async () => {
|
||||
interface Result {
|
||||
path: string,
|
||||
args: any[],
|
||||
}
|
||||
|
||||
const results:Result[] = [];
|
||||
|
||||
const target:Target = (path:string, args:any[]) => {
|
||||
results.push({ path, args });
|
||||
};
|
||||
|
||||
const proxy = sandboxProxy(target);
|
||||
|
||||
proxy.testing.bla.test('hello', '123');
|
||||
proxy.testing.test2();
|
||||
|
||||
expect(results[0].path).toBe('testing.bla.test');
|
||||
expect(results[0].args.join('_')).toBe('hello_123');
|
||||
expect(results[1].path).toBe('testing.test2');
|
||||
expect(results[1].args.join('_')).toBe('');
|
||||
}));
|
||||
|
||||
it('should allow importing a namespace', asyncTest(async () => {
|
||||
interface Result {
|
||||
path: string,
|
||||
args: any[],
|
||||
}
|
||||
|
||||
const results:Result[] = [];
|
||||
|
||||
const target:Target = (path:string, args:any[]) => {
|
||||
results.push({ path, args });
|
||||
};
|
||||
|
||||
const proxy = sandboxProxy(target);
|
||||
|
||||
const ns = proxy.testing.blabla;
|
||||
ns.test();
|
||||
ns.test2();
|
||||
|
||||
expect(results[0].path).toBe('testing.blabla.test');
|
||||
expect(results[1].path).toBe('testing.blabla.test2');
|
||||
}));
|
||||
|
||||
});
|
278
CliClient/tests/services_CommandService.ts
Normal file
278
CliClient/tests/services_CommandService.ts
Normal file
@@ -0,0 +1,278 @@
|
||||
import MenuUtils from 'lib/services/commands/MenuUtils';
|
||||
import ToolbarButtonUtils from 'lib/services/commands/ToolbarButtonUtils';
|
||||
import CommandService, { CommandDeclaration, CommandRuntime } from 'lib/services/CommandService';
|
||||
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
|
||||
|
||||
interface TestCommand {
|
||||
declaration: CommandDeclaration,
|
||||
runtime: CommandRuntime,
|
||||
}
|
||||
|
||||
function newService():CommandService {
|
||||
const service = new CommandService();
|
||||
service.initialize({});
|
||||
return service;
|
||||
}
|
||||
|
||||
function createCommand(name:string, options:any):TestCommand {
|
||||
const declaration:CommandDeclaration = {
|
||||
name: name,
|
||||
};
|
||||
|
||||
const runtime:CommandRuntime = {
|
||||
execute: options.execute,
|
||||
};
|
||||
|
||||
if (options.mapStateToProps) runtime.mapStateToProps = options.mapStateToProps;
|
||||
if (options.isEnabled) runtime.isEnabled = options.isEnabled;
|
||||
|
||||
return { declaration, runtime };
|
||||
}
|
||||
|
||||
function registerCommand(service:CommandService, cmd:TestCommand) {
|
||||
service.registerDeclaration(cmd.declaration);
|
||||
service.registerRuntime(cmd.declaration.name, cmd.runtime);
|
||||
}
|
||||
|
||||
describe('services_CommandService', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should create toolbar button infos from commands', asyncTest(async () => {
|
||||
const service = newService();
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(service);
|
||||
|
||||
const executedCommands:string[] = [];
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: () => {
|
||||
executedCommands.push('test1');
|
||||
},
|
||||
}));
|
||||
|
||||
registerCommand(service, createCommand('test2', {
|
||||
execute: () => {
|
||||
executedCommands.push('test2');
|
||||
},
|
||||
}));
|
||||
|
||||
const toolbarInfos = toolbarButtonUtils.commandsToToolbarButtons({}, ['test1', 'test2']);
|
||||
|
||||
await toolbarInfos[0].onClick();
|
||||
await toolbarInfos[1].onClick();
|
||||
|
||||
expect(executedCommands.join('_')).toBe('test1_test2');
|
||||
expect(toolbarInfos[0].enabled).toBe(true);
|
||||
expect(toolbarInfos[1].enabled).toBe(true);
|
||||
}));
|
||||
|
||||
it('should enable and disable toolbar buttons depending on state', asyncTest(async () => {
|
||||
const service = newService();
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(service);
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: () => {},
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
selectedNoteId: state.selectedNoteId,
|
||||
selectedFolderId: state.selectedFolderId,
|
||||
};
|
||||
},
|
||||
isEnabled: (props:any) => {
|
||||
return props.selectedNoteId === 'abc';
|
||||
},
|
||||
}));
|
||||
|
||||
registerCommand(service, createCommand('test2', {
|
||||
execute: () => {},
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
selectedNoteId: state.selectedNoteId,
|
||||
selectedFolderId: state.selectedFolderId,
|
||||
};
|
||||
},
|
||||
isEnabled: (props:any) => {
|
||||
return props.selectedNoteId === '123';
|
||||
},
|
||||
}));
|
||||
|
||||
const toolbarInfos = toolbarButtonUtils.commandsToToolbarButtons({
|
||||
selectedNoteId: '123',
|
||||
selectedFolderId: 'aaa',
|
||||
}, ['test1', 'test2']);
|
||||
|
||||
expect(toolbarInfos[0].enabled).toBe(false);
|
||||
expect(toolbarInfos[1].enabled).toBe(true);
|
||||
}));
|
||||
|
||||
it('should return the same toolbarButtons array if nothing has changed', asyncTest(async () => {
|
||||
const service = newService();
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(service);
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: () => {},
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
selectedNoteId: state.selectedNoteId,
|
||||
};
|
||||
},
|
||||
isEnabled: (props:any) => {
|
||||
return props.selectedNoteId === 'ok';
|
||||
},
|
||||
}));
|
||||
|
||||
registerCommand(service, createCommand('test2', {
|
||||
execute: () => {},
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
selectedFolderId: state.selectedFolderId,
|
||||
};
|
||||
},
|
||||
isEnabled: (props:any) => {
|
||||
return props.selectedFolderId === 'ok';
|
||||
},
|
||||
}));
|
||||
|
||||
const toolbarInfos1 = toolbarButtonUtils.commandsToToolbarButtons({
|
||||
selectedNoteId: 'ok',
|
||||
selectedFolderId: 'notok',
|
||||
}, ['test1', 'test2']);
|
||||
|
||||
const toolbarInfos2 = toolbarButtonUtils.commandsToToolbarButtons({
|
||||
selectedNoteId: 'ok',
|
||||
selectedFolderId: 'notok',
|
||||
}, ['test1', 'test2']);
|
||||
|
||||
expect(toolbarInfos1).toBe(toolbarInfos2);
|
||||
expect(toolbarInfos1[0] === toolbarInfos2[0]).toBe(true);
|
||||
expect(toolbarInfos1[1] === toolbarInfos2[1]).toBe(true);
|
||||
|
||||
const toolbarInfos3 = toolbarButtonUtils.commandsToToolbarButtons({
|
||||
selectedNoteId: 'ok',
|
||||
selectedFolderId: 'ok',
|
||||
}, ['test1', 'test2']);
|
||||
|
||||
expect(toolbarInfos2 === toolbarInfos3).toBe(false);
|
||||
expect(toolbarInfos2[0] === toolbarInfos3[0]).toBe(true);
|
||||
expect(toolbarInfos2[1] === toolbarInfos3[1]).toBe(false);
|
||||
|
||||
{
|
||||
expect(toolbarButtonUtils.commandsToToolbarButtons({
|
||||
selectedNoteId: 'ok',
|
||||
selectedFolderId: 'notok',
|
||||
}, ['test1', '-', 'test2'])).toBe(toolbarButtonUtils.commandsToToolbarButtons({
|
||||
selectedNoteId: 'ok',
|
||||
selectedFolderId: 'notok',
|
||||
}, ['test1', '-', 'test2']));
|
||||
}
|
||||
}));
|
||||
|
||||
it('should create menu items from commands', asyncTest(async () => {
|
||||
const service = newService();
|
||||
const utils = new MenuUtils(service);
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: () => {},
|
||||
}));
|
||||
|
||||
registerCommand(service, createCommand('test2', {
|
||||
execute: () => {},
|
||||
}));
|
||||
|
||||
const clickedCommands:string[] = [];
|
||||
|
||||
const onClick = (commandName:string) => {
|
||||
clickedCommands.push(commandName);
|
||||
};
|
||||
|
||||
const menuItems = utils.commandsToMenuItems(['test1', 'test2'], onClick);
|
||||
|
||||
menuItems.test1.click();
|
||||
menuItems.test2.click();
|
||||
|
||||
expect(clickedCommands.join('_')).toBe('test1_test2');
|
||||
|
||||
// Also check that the same commands always return strictly the same menu
|
||||
expect(utils.commandsToMenuItems(['test1', 'test2'], onClick)).toBe(utils.commandsToMenuItems(['test1', 'test2'], onClick));
|
||||
}));
|
||||
|
||||
it('should give menu item props from state', asyncTest(async () => {
|
||||
const service = newService();
|
||||
const utils = new MenuUtils(service);
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
isOk: state.test1 === 'ok',
|
||||
};
|
||||
},
|
||||
execute: () => {},
|
||||
}));
|
||||
|
||||
registerCommand(service, createCommand('test2', {
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
isOk: state.test2 === 'ok',
|
||||
};
|
||||
},
|
||||
execute: () => {},
|
||||
}));
|
||||
|
||||
{
|
||||
const menuItemProps = utils.commandsToMenuItemProps({
|
||||
test1: 'ok',
|
||||
test2: 'notok',
|
||||
}, ['test1', 'test2']);
|
||||
|
||||
expect(menuItemProps.test1.isOk).toBe(true);
|
||||
expect(menuItemProps.test2.isOk).toBe(false);
|
||||
}
|
||||
|
||||
{
|
||||
const menuItemProps = utils.commandsToMenuItemProps({
|
||||
test1: 'ok',
|
||||
test2: 'ok',
|
||||
}, ['test1', 'test2']);
|
||||
|
||||
expect(menuItemProps.test1.isOk).toBe(true);
|
||||
expect(menuItemProps.test2.isOk).toBe(true);
|
||||
}
|
||||
|
||||
expect(utils.commandsToMenuItemProps({
|
||||
test1: 'ok',
|
||||
test2: 'ok',
|
||||
}, ['test1', 'test2'])).toBe(utils.commandsToMenuItemProps({
|
||||
test1: 'ok',
|
||||
test2: 'ok',
|
||||
}, ['test1', 'test2']));
|
||||
}));
|
||||
|
||||
it('should create stateful menu items', asyncTest(async () => {
|
||||
const service = newService();
|
||||
const utils = new MenuUtils(service);
|
||||
|
||||
let propValue = null;
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
mapStateToProps: (state:any) => {
|
||||
return {
|
||||
isOk: state.test1 === 'ok',
|
||||
};
|
||||
},
|
||||
execute: (props:any) => {
|
||||
propValue = props.isOk;
|
||||
},
|
||||
}));
|
||||
|
||||
const menuItem = utils.commandToStatefulMenuItem('test1', { isOk: 'hello' });
|
||||
menuItem.click();
|
||||
|
||||
expect(propValue).toBe('hello');
|
||||
}));
|
||||
|
||||
});
|
@@ -8,7 +8,7 @@ const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const MasterKey = require('lib/models/MasterKey');
|
||||
@@ -289,35 +289,4 @@ describe('services_EncryptionService', function() {
|
||||
const plainText = await service.decryptString(cipherText);
|
||||
expect(plainText).toBe('🐶🐶🐶'.substr(0,5));
|
||||
}));
|
||||
|
||||
// it('should upgrade master key encryption mode', asyncTest(async () => {
|
||||
// let masterKey = await service.generateMasterKey('123456', {
|
||||
// encryptionMethod: EncryptionService.METHOD_SJCL_2,
|
||||
// });
|
||||
// masterKey = await MasterKey.save(masterKey);
|
||||
// Setting.setObjectKey('encryption.passwordCache', masterKey.id, '123456');
|
||||
// Setting.setValue('encryption.activeMasterKeyId', masterKey.id);
|
||||
|
||||
// await sleep(0.01);
|
||||
|
||||
// await service.loadMasterKeysFromSettings();
|
||||
|
||||
// masterKeyNew = await MasterKey.load(masterKey.id);
|
||||
|
||||
// // Check that the master key has been upgraded
|
||||
|
||||
// expect(masterKeyNew.created_time).toBe(masterKey.created_time);
|
||||
// expect(masterKeyNew.updated_time === masterKey.updated_time).toBe(false);
|
||||
// expect(masterKeyNew.content === masterKey.content).toBe(false);
|
||||
// expect(masterKeyNew.encryption_method === masterKey.encryption_method).toBe(false);
|
||||
// expect(masterKeyNew.checksum === masterKey.checksum).toBe(false);
|
||||
// expect(masterKeyNew.encryption_method).toBe(service.defaultMasterKeyEncryptionMethod_);
|
||||
|
||||
// // Check that encryption still works
|
||||
|
||||
// const cipherText = await service.encryptString('some secret');
|
||||
// const plainText = await service.decryptString(cipherText);
|
||||
// expect(plainText).toBe('some secret');
|
||||
// }));
|
||||
|
||||
});
|
||||
|
@@ -1,19 +1,16 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
import InteropService from 'lib/services/interop/InteropService';
|
||||
import { CustomExportContext, CustomImportContext, Module, ModuleType } from 'lib/services/interop/types';
|
||||
import shim from 'lib/shim';
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { asyncTest, fileContentEqual, expectNotThrow, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const { asyncTest, fileContentEqual, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('test-utils.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const NoteTag = require('lib/models/NoteTag.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const fs = require('fs-extra');
|
||||
const ArrayUtils = require('lib/ArrayUtils');
|
||||
const ObjectUtils = require('lib/ObjectUtils');
|
||||
const { shim } = require('lib/shim.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
@@ -23,7 +20,7 @@ function exportDir() {
|
||||
return `${__dirname}/export`;
|
||||
}
|
||||
|
||||
function fieldsEqual(model1, model2, fieldNames) {
|
||||
function fieldsEqual(model1:any, model2:any, fieldNames:string[]) {
|
||||
for (let i = 0; i < fieldNames.length; i++) {
|
||||
const f = fieldNames[i];
|
||||
expect(model1[f]).toBe(model2[f], `For key ${f}`);
|
||||
@@ -43,7 +40,7 @@ describe('services_InteropService', function() {
|
||||
});
|
||||
|
||||
it('should export and import folders', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
let folder1 = await Folder.save({ title: 'folder1' });
|
||||
folder1 = await Folder.load(folder1.id);
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
@@ -78,7 +75,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should import folders and de-duplicate titles when needed', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const folder1 = await Folder.save({ title: 'folder' });
|
||||
const folder2 = await Folder.save({ title: 'folder' });
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
@@ -90,15 +87,15 @@ describe('services_InteropService', function() {
|
||||
await service.import({ path: filePath });
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.map(f => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||
expect(allFolders.map((f:any) => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||
}));
|
||||
|
||||
it('should import folders, and only de-duplicate titles when needed', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const folder2 = await Folder.save({ title: 'folder2' });
|
||||
const sub1 = await Folder.save({ title: 'Sub', parent_id: folder1.id });
|
||||
const sub2 = await Folder.save({ title: 'Sub', parent_id: folder2.id });
|
||||
await Folder.save({ title: 'Sub', parent_id: folder1.id });
|
||||
await Folder.save({ title: 'Sub', parent_id: folder2.id });
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
await service.export({ path: filePath });
|
||||
|
||||
@@ -117,7 +114,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import folders and notes', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
note1 = await Note.load(note1.id);
|
||||
@@ -156,7 +153,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import notes to specific folder', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
note1 = await Note.load(note1.id);
|
||||
@@ -175,7 +172,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import tags', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
@@ -215,7 +212,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import resources', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
@@ -251,7 +248,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import single notes', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
@@ -271,7 +268,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import single folders', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
@@ -292,7 +289,7 @@ describe('services_InteropService', function() {
|
||||
|
||||
it('should export and import folder and its sub-folders', asyncTest(async () => {
|
||||
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||
@@ -326,7 +323,7 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export and import links to notes', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const filePath = `${exportDir()}/test.jex`;
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
@@ -349,43 +346,21 @@ describe('services_InteropService', function() {
|
||||
expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true);
|
||||
}));
|
||||
|
||||
it('should export into json format', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
note1 = await Note.load(note1.id);
|
||||
const filePath = exportDir();
|
||||
|
||||
await service.export({ path: filePath, format: 'json' });
|
||||
|
||||
// verify that the json files exist and can be parsed
|
||||
const items = [folder1, note1];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const jsonFile = `${filePath}/${items[i].id}.json`;
|
||||
const json = await fs.readFile(jsonFile, 'utf-8');
|
||||
const obj = JSON.parse(json);
|
||||
expect(obj.id).toBe(items[i].id);
|
||||
expect(obj.type_).toBe(items[i].type_);
|
||||
expect(obj.title).toBe(items[i].title);
|
||||
expect(obj.body).toBe(items[i].body);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should export selected notes in md format', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
let note11 = await Note.save({ title: 'title note11', parent_id: folder1.id });
|
||||
note11 = await Note.load(note11.id);
|
||||
let note12 = await Note.save({ title: 'title note12', parent_id: folder1.id });
|
||||
note12 = await Note.load(note12.id);
|
||||
const note12 = await Note.save({ title: 'title note12', parent_id: folder1.id });
|
||||
await Note.load(note12.id);
|
||||
|
||||
let folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
|
||||
folder2 = await Folder.load(folder2.id);
|
||||
let note21 = await Note.save({ title: 'title note21', parent_id: folder2.id });
|
||||
note21 = await Note.load(note21.id);
|
||||
|
||||
let folder3 = await Folder.save({ title: 'folder3', parent_id: folder1.id });
|
||||
folder3 = await Folder.load(folder2.id);
|
||||
await Folder.save({ title: 'folder3', parent_id: folder1.id });
|
||||
await Folder.load(folder2.id);
|
||||
|
||||
const outDir = exportDir();
|
||||
|
||||
@@ -401,16 +376,16 @@ describe('services_InteropService', function() {
|
||||
}));
|
||||
|
||||
it('should export MD with unicode filenames', asyncTest(async () => {
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const folder2 = await Folder.save({ title: 'ジョプリン' });
|
||||
const note1 = await Note.save({ title: '生活', parent_id: folder1.id });
|
||||
const note2 = await Note.save({ title: '生活', parent_id: folder1.id });
|
||||
const note2b = await Note.save({ title: '生活', parent_id: folder1.id });
|
||||
const note3 = await Note.save({ title: '', parent_id: folder1.id });
|
||||
const note4 = await Note.save({ title: '', parent_id: folder1.id });
|
||||
const note5 = await Note.save({ title: 'salut, ça roule ?', parent_id: folder1.id });
|
||||
const note6 = await Note.save({ title: 'ジョプリン', parent_id: folder2.id });
|
||||
await Note.save({ title: '生活', parent_id: folder1.id });
|
||||
await Note.save({ title: '生活', parent_id: folder1.id });
|
||||
await Note.save({ title: '生活', parent_id: folder1.id });
|
||||
await Note.save({ title: '', parent_id: folder1.id });
|
||||
await Note.save({ title: '', parent_id: folder1.id });
|
||||
await Note.save({ title: 'salut, ça roule ?', parent_id: folder1.id });
|
||||
await Note.save({ title: 'ジョプリン', parent_id: folder2.id });
|
||||
|
||||
const outDir = exportDir();
|
||||
|
||||
@@ -430,7 +405,7 @@ describe('services_InteropService', function() {
|
||||
await Note.save({ title: 'textexportnote1', parent_id: folder1.id });
|
||||
await Note.save({ title: 'textexportnote2', parent_id: folder1.id });
|
||||
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
|
||||
await service.export({
|
||||
path: exportDir(),
|
||||
@@ -454,7 +429,7 @@ describe('services_InteropService', function() {
|
||||
|
||||
await Folder.save({ title: 'orphan', parent_id: '0c5bbd8a1b5a48189484a412a7e534cc' });
|
||||
|
||||
const service = new InteropService();
|
||||
const service = InteropService.instance();
|
||||
|
||||
const result = await service.export({
|
||||
path: exportDir(),
|
||||
@@ -464,4 +439,99 @@ describe('services_InteropService', function() {
|
||||
expect(result.warnings.length).toBe(0);
|
||||
}));
|
||||
|
||||
it('should allow registering new import modules', asyncTest(async () => {
|
||||
const testImportFilePath = `${exportDir()}/testImport${Math.random()}.test`;
|
||||
await shim.fsDriver().writeFile(testImportFilePath, 'test', 'utf8');
|
||||
|
||||
const result = {
|
||||
hasBeenExecuted: false,
|
||||
sourcePath: '',
|
||||
};
|
||||
|
||||
const module:Module = {
|
||||
type: ModuleType.Importer,
|
||||
description: 'Test Import Module',
|
||||
format: 'testing',
|
||||
fileExtensions: ['test'],
|
||||
isCustom: true,
|
||||
|
||||
onExec: async (context:CustomImportContext) => {
|
||||
result.hasBeenExecuted = true;
|
||||
result.sourcePath = context.sourcePath;
|
||||
},
|
||||
};
|
||||
|
||||
const service = InteropService.instance();
|
||||
service.registerModule(module);
|
||||
await service.import({
|
||||
format: 'testing',
|
||||
path: testImportFilePath,
|
||||
});
|
||||
|
||||
expect(result.hasBeenExecuted).toBe(true);
|
||||
expect(result.sourcePath).toBe(testImportFilePath);
|
||||
}));
|
||||
|
||||
it('should allow registering new export modules', asyncTest(async () => {
|
||||
const folder1 = await Folder.save({ title: 'folder1' });
|
||||
const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
|
||||
await Note.save({ title: 'note2', parent_id: folder1.id });
|
||||
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
|
||||
|
||||
const filePath = `${exportDir()}/example.test`;
|
||||
|
||||
const result:any = {
|
||||
destPath: '',
|
||||
itemTypes: [],
|
||||
items: [],
|
||||
resources: [],
|
||||
filePaths: [],
|
||||
closeCalled: false,
|
||||
};
|
||||
|
||||
const module:Module = {
|
||||
type: ModuleType.Exporter,
|
||||
description: 'Test Export Module',
|
||||
format: 'testing',
|
||||
fileExtensions: ['test'],
|
||||
isCustom: true,
|
||||
|
||||
onInit: async (context:CustomExportContext) => {
|
||||
result.destPath = context.destPath;
|
||||
},
|
||||
|
||||
onProcessItem: async (_context:CustomExportContext, itemType:number, item:any) => {
|
||||
result.itemTypes.push(itemType);
|
||||
result.items.push(item);
|
||||
},
|
||||
|
||||
onProcessResource: async (_context:CustomExportContext, resource:any, filePath:string) => {
|
||||
result.resources.push(resource);
|
||||
result.filePaths.push(filePath);
|
||||
},
|
||||
|
||||
onClose: async (_context:CustomExportContext) => {
|
||||
result.closeCalled = true;
|
||||
},
|
||||
};
|
||||
|
||||
const service = InteropService.instance();
|
||||
service.registerModule(module);
|
||||
await service.export({
|
||||
format: 'testing',
|
||||
path: filePath,
|
||||
});
|
||||
|
||||
expect(result.destPath).toBe(filePath);
|
||||
expect(result.itemTypes.sort().join('_')).toBe('1_1_2_4');
|
||||
expect(result.items.length).toBe(4);
|
||||
expect(result.items.map((o:any) => o.title).sort().join('_')).toBe('folder1_note1_note2_photo.jpg');
|
||||
expect(result.resources.length).toBe(1);
|
||||
expect(result.resources[0].title).toBe('photo.jpg');
|
||||
expect(result.filePaths.length).toBe(1);
|
||||
expect(!!result.filePaths[0]).toBe(true);
|
||||
expect(result.closeCalled).toBe(true);
|
||||
}));
|
||||
|
||||
|
||||
});
|
@@ -4,12 +4,12 @@ require('app-module-path').addPath(__dirname);
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
|
||||
const InteropService_Exporter_Md = require('lib/services/InteropService_Exporter_Md.js');
|
||||
const InteropService_Exporter_Md = require('lib/services/interop/InteropService_Exporter_Md').default;
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
const exportDir = `${__dirname}/export`;
|
||||
|
||||
@@ -67,8 +67,8 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
|
||||
expect(!exporter.context() && !(exporter.context().notePaths || Object.keys(exporter.context().notePaths).length)).toBe(false, 'Context should be empty before processing.');
|
||||
|
||||
await exporter.processItem(Folder, folder1);
|
||||
await exporter.processItem(Folder, folder2);
|
||||
await exporter.processItem(Folder.modelType(), folder1);
|
||||
await exporter.processItem(Folder.modelType(), folder2);
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
|
||||
expect(Object.keys(exporter.context().notePaths).length).toBe(3, 'There should be 3 note paths in the context.');
|
||||
@@ -96,7 +96,7 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note1_2);
|
||||
|
||||
await exporter.processItem(Folder, folder1);
|
||||
await exporter.processItem(Folder.modelType(), folder1);
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
|
||||
expect(Object.keys(exporter.context().notePaths).length).toBe(2, 'There should be 2 note paths in the context.');
|
||||
@@ -121,7 +121,7 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||
|
||||
await exporter.processItem(Folder, folder1);
|
||||
await exporter.processItem(Folder.modelType(), folder1);
|
||||
// Create a file with the path of note1 before processing note1
|
||||
await shim.fsDriver().writeFile(`${exportDir}/folder1/note1.md`, 'Note content', 'utf-8');
|
||||
|
||||
@@ -189,10 +189,10 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
const folder3 = await Folder.save({ title: 'folder3', parent_id: folder1.id });
|
||||
queueExportItem(BaseModel.TYPE_FOLDER, folder3.id);
|
||||
|
||||
await exporter.processItem(Folder, folder2);
|
||||
await exporter.processItem(Folder, folder3);
|
||||
await exporter.processItem(Folder.modelType(), folder2);
|
||||
await exporter.processItem(Folder.modelType(), folder3);
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
await exporter.processItem(Note, note2);
|
||||
await exporter.processItem(Note.modelType(), note2);
|
||||
|
||||
expect(await shim.fsDriver().exists(`${exportDir}/folder1`)).toBe(true, 'Folder should be created in filesystem.');
|
||||
expect(await shim.fsDriver().exists(`${exportDir}/folder1/folder2`)).toBe(true, 'Folder should be created in filesystem.');
|
||||
@@ -227,9 +227,9 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note3);
|
||||
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
await exporter.processItem(Note, note1);
|
||||
await exporter.processItem(Note, note2);
|
||||
await exporter.processItem(Note, note3);
|
||||
await exporter.processItem(Note.modelType(), note1);
|
||||
await exporter.processItem(Note.modelType(), note2);
|
||||
await exporter.processItem(Note.modelType(), note3);
|
||||
|
||||
expect(await shim.fsDriver().exists(`${exportDir}/${exporter.context().notePaths[note1.id]}`)).toBe(true, 'File should be saved in filesystem.');
|
||||
expect(await shim.fsDriver().exists(`${exportDir}/${exporter.context().notePaths[note2.id]}`)).toBe(true, 'File should be saved in filesystem.');
|
||||
@@ -262,8 +262,8 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||
const resource2 = await Resource.load((await Note.linkedResourceIds(note2.body))[0]);
|
||||
|
||||
await exporter.processItem(Folder, folder1);
|
||||
await exporter.processItem(Folder, folder2);
|
||||
await exporter.processItem(Folder.modelType(), folder1);
|
||||
await exporter.processItem(Folder.modelType(), folder2);
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
const context = {
|
||||
resourcePaths: {},
|
||||
@@ -271,8 +271,8 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
context.resourcePaths[resource1.id] = 'resource1.jpg';
|
||||
context.resourcePaths[resource2.id] = 'resource2.jpg';
|
||||
exporter.updateContext(context);
|
||||
await exporter.processItem(Note, note1);
|
||||
await exporter.processItem(Note, note2);
|
||||
await exporter.processItem(Note.modelType(), note1);
|
||||
await exporter.processItem(Note.modelType(), note2);
|
||||
|
||||
const note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
|
||||
const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
||||
@@ -315,13 +315,13 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note3);
|
||||
|
||||
await exporter.processItem(Folder, folder1);
|
||||
await exporter.processItem(Folder, folder2);
|
||||
await exporter.processItem(Folder, folder3);
|
||||
await exporter.processItem(Folder.modelType(), folder1);
|
||||
await exporter.processItem(Folder.modelType(), folder2);
|
||||
await exporter.processItem(Folder.modelType(), folder3);
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
await exporter.processItem(Note, note1);
|
||||
await exporter.processItem(Note, note2);
|
||||
await exporter.processItem(Note, note3);
|
||||
await exporter.processItem(Note.modelType(), note1);
|
||||
await exporter.processItem(Note.modelType(), note2);
|
||||
await exporter.processItem(Note.modelType(), note3);
|
||||
|
||||
const note1_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note1.id]}`);
|
||||
const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
||||
@@ -351,10 +351,10 @@ describe('services_InteropService_Exporter_Md', function() {
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note1);
|
||||
queueExportItem(BaseModel.TYPE_NOTE, note2);
|
||||
|
||||
await exporter.processItem(Folder, folder1);
|
||||
await exporter.processItem(Folder.modelType(), folder1);
|
||||
await exporter.prepareForProcessingItemType(BaseModel.TYPE_NOTE, itemsToExport);
|
||||
await exporter.processItem(Note, note1);
|
||||
await exporter.processItem(Note, note2);
|
||||
await exporter.processItem(Note.modelType(), note1);
|
||||
await exporter.processItem(Note.modelType(), note2);
|
||||
|
||||
const note2_body = await shim.fsDriver().readFile(`${exportDir}/${exporter.context().notePaths[note2.id]}`);
|
||||
expect(note2_body).toContain('[link](../folder%20with%20space1/note1%20name%20with%20space.md)', 'Whitespace in URL should be encoded');
|
||||
|
@@ -1,5 +1,6 @@
|
||||
require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { tempFilePath } = require('test-utils.js');
|
||||
const KeymapService = require('lib/services/KeymapService').default;
|
||||
const keymapService = KeymapService.instance();
|
||||
|
||||
@@ -76,6 +77,31 @@ describe('services_KeymapService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('registerCommandAccelerator', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
|
||||
it('should allow registering new commands', async () => {
|
||||
keymapService.initialize('linux');
|
||||
keymapService.registerCommandAccelerator('myCustomCommand', 'Ctrl+Shift+Alt+B');
|
||||
expect(keymapService.getAccelerator('myCustomCommand')).toEqual('Ctrl+Shift+Alt+B');
|
||||
|
||||
// Check that macOS key conversion is working
|
||||
keymapService.initialize('darwin');
|
||||
keymapService.registerCommandAccelerator('myCustomCommand', 'CmdOrCtrl+Shift+Alt+B');
|
||||
expect(keymapService.getAccelerator('myCustomCommand')).toEqual('Cmd+Shift+Option+B');
|
||||
keymapService.setAccelerator('myCustomCommand', 'Cmd+Shift+Option+X');
|
||||
|
||||
// Check that the new custom shortcut is being saved and loaded
|
||||
const keymapFilePath = tempFilePath('json');
|
||||
await keymapService.saveCustomKeymap(keymapFilePath);
|
||||
|
||||
keymapService.initialize('darwin');
|
||||
await keymapService.loadCustomKeymap(keymapFilePath);
|
||||
|
||||
expect(keymapService.getAccelerator('myCustomCommand')).toEqual('Cmd+Shift+Option+X');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAccelerator', () => {
|
||||
beforeEach(() => keymapService.initialize());
|
||||
|
||||
@@ -254,15 +280,15 @@ describe('services_KeymapService', () => {
|
||||
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
|
||||
});
|
||||
|
||||
it('should throw when the provided commands are invalid', () => {
|
||||
const customKeymapItems = [
|
||||
{ command: 'totallyInvalidCommand', accelerator: 'Ctrl+Shift+G' },
|
||||
{ command: 'print', accelerator: 'Alt+P' },
|
||||
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J' },
|
||||
];
|
||||
// it('should throw when the provided commands are invalid', () => {
|
||||
// const customKeymapItems = [
|
||||
// { command: 'totallyInvalidCommand', accelerator: 'Ctrl+Shift+G' },
|
||||
// { command: 'print', accelerator: 'Alt+P' },
|
||||
// { command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J' },
|
||||
// ];
|
||||
|
||||
expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
|
||||
});
|
||||
// expect(() => keymapService.overrideKeymap(customKeymapItems)).toThrow();
|
||||
// });
|
||||
|
||||
it('should throw when duplicate accelerators are provided', () => {
|
||||
const customKeymaps_Darwin = [
|
||||
|
93
CliClient/tests/services_PluginService.ts
Normal file
93
CliClient/tests/services_PluginService.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import PluginRunner from '../app/services/plugins/PluginRunner';
|
||||
import PluginService from 'lib/services/plugins/PluginService';
|
||||
|
||||
require('app-module-path').addPath(__dirname);
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
|
||||
const Note = require('lib/models/Note');
|
||||
const Folder = require('lib/models/Folder');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
const testPluginDir = `${__dirname}/../tests/support/plugins`;
|
||||
|
||||
function newPluginService() {
|
||||
const runner = new PluginRunner();
|
||||
const service = new PluginService();
|
||||
service.initialize(
|
||||
{
|
||||
joplin: {
|
||||
workspace: {},
|
||||
},
|
||||
},
|
||||
runner,
|
||||
{
|
||||
dispatch: () => {},
|
||||
getState: () => {},
|
||||
}
|
||||
);
|
||||
return service;
|
||||
}
|
||||
|
||||
describe('services_PluginService', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should load and run a simple plugin', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
const plugin = await service.loadPlugin(`${testPluginDir}/simple`);
|
||||
await service.runPlugin(plugin);
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.length).toBe(1);
|
||||
expect(allFolders[0].title).toBe('my plugin folder');
|
||||
|
||||
const allNotes = await Note.all();
|
||||
expect(allNotes.length).toBe(1);
|
||||
expect(allNotes[0].title).toBe('testing plugin!');
|
||||
expect(allNotes[0].parent_id).toBe(allFolders[0].id);
|
||||
}));
|
||||
|
||||
it('should load and run a plugin that uses external packages', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
const plugin = await service.loadPlugin(`${testPluginDir}/withExternalModules`);
|
||||
expect(plugin.id).toBe('withexternalmodules');
|
||||
await service.runPlugin(plugin);
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.length).toBe(1);
|
||||
expect(allFolders[0].title).toBe(' foo');
|
||||
}));
|
||||
|
||||
it('should load multiple plugins from a directory', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins(`${testPluginDir}/multi_plugins`);
|
||||
|
||||
const plugin1 = service.pluginById('simple1');
|
||||
const plugin2 = service.pluginById('simple2');
|
||||
expect(!!plugin1).toBe(true);
|
||||
expect(!!plugin2).toBe(true);
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.length).toBe(2);
|
||||
expect(allFolders.map((f:any) => f.title).sort().join(', ')).toBe('multi - simple1, multi - simple2');
|
||||
}));
|
||||
|
||||
// it('should translate calls from plugin process to sandbox', asyncTest(async () => {
|
||||
// const service = newPluginService();
|
||||
// const plugin = await service.loadPlugin(`${testPluginDir}/simple`);
|
||||
// await service.runPlugin(plugin);
|
||||
|
||||
// const folder = await Folder.save({ title: 'folder' });
|
||||
|
||||
// const folderFromApi = await service.executeSandboxCall(plugin.id, 'joplin.data.get', ['folders/' + folder.id]);
|
||||
// expect(folder.id).toBe(folderFromApi.id);
|
||||
// expect(folder.title).toBe(folderFromApi.title);
|
||||
// }));
|
||||
|
||||
});
|
@@ -4,7 +4,7 @@ require('app-module-path').addPath(__dirname);
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { asyncTest, resourceService, decryptionWorker, encryptionService, loadEncryptionMasterKey, allSyncTargetItemsEncrypted, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const InteropService = require('lib/services/interop/InteropService').default;
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
@@ -16,7 +16,7 @@ const ResourceService = require('lib/services/ResourceService.js');
|
||||
const fs = require('fs-extra');
|
||||
const ArrayUtils = require('lib/ArrayUtils');
|
||||
const ObjectUtils = require('lib/ObjectUtils');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const shim = require('lib/shim').default;
|
||||
const SearchEngine = require('lib/services/searchengine/SearchEngine');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
|
@@ -5,7 +5,7 @@ require('app-module-path').addPath(__dirname);
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { asyncTest, fileContentEqual, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Note = require('lib/models/Note.js');
|
||||
const NoteTag = require('lib/models/NoteTag.js');
|
||||
const ItemChange = require('lib/models/ItemChange.js');
|
||||
@@ -13,7 +13,7 @@ const Tag = require('lib/models/Tag.js');
|
||||
const Revision = require('lib/models/Revision.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const RevisionService = require('lib/services/RevisionService.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -8,7 +8,7 @@ const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest
|
||||
const SearchEngine = require('lib/services/searchengine/SearchEngine');
|
||||
const Note = require('lib/models/Note');
|
||||
const ItemChange = require('lib/models/ItemChange');
|
||||
const Setting = require('lib/models/Setting');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -10,9 +10,9 @@ const Note = require('lib/models/Note');
|
||||
const Folder = require('lib/models/Folder');
|
||||
const Tag = require('lib/models/Tag');
|
||||
const ItemChange = require('lib/models/ItemChange');
|
||||
const Setting = require('lib/models/Setting');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
const ResourceService = require('lib/services/ResourceService.js');
|
||||
|
||||
|
||||
|
@@ -12,10 +12,9 @@
|
||||
// const ItemChange = require('lib/models/ItemChange');
|
||||
// const Setting = require('lib/models/Setting');
|
||||
// const Resource = require('lib/models/Resource.js');
|
||||
// const { shim } = require('lib/shim');
|
||||
// const shim = require('lib/shim').default;
|
||||
// const ResourceService = require('lib/services/ResourceService.js');
|
||||
|
||||
|
||||
// process.on('unhandledRejection', (reason, p) => {
|
||||
// console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
// });
|
||||
|
@@ -1,84 +0,0 @@
|
||||
// /* eslint-disable no-unused-vars */
|
||||
|
||||
// require('app-module-path').addPath(__dirname);
|
||||
|
||||
// const { asyncTest, fileContentEqual, setupDatabase, checkThrow, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
|
||||
// const KvStore = require('lib/services/KvStore.js');
|
||||
// const UndoRedoService = require('lib/services/UndoRedoService.js').default;
|
||||
|
||||
// process.on('unhandledRejection', (reason, p) => {
|
||||
// console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
// });
|
||||
|
||||
// describe('services_UndoRedoService', function() {
|
||||
|
||||
// beforeEach(async (done) => {
|
||||
// await setupDatabaseAndSynchronizer(1);
|
||||
// await switchClient(1);
|
||||
// done();
|
||||
// });
|
||||
|
||||
// it('should undo and redo', asyncTest(async () => {
|
||||
// const service = new UndoRedoService();
|
||||
|
||||
// expect(service.canUndo).toBe(false);
|
||||
// expect(service.canRedo).toBe(false);
|
||||
|
||||
// service.push('test');
|
||||
// expect(service.canUndo).toBe(true);
|
||||
// expect(service.canRedo).toBe(false);
|
||||
// service.push('test 2');
|
||||
// service.push('test 3');
|
||||
|
||||
// expect(service.undo()).toBe('test 3');
|
||||
// expect(service.canRedo).toBe(true);
|
||||
// expect(service.undo()).toBe('test 2');
|
||||
// expect(service.undo()).toBe('test');
|
||||
|
||||
// expect(checkThrow(() => service.undo())).toBe(true);
|
||||
|
||||
// expect(service.canUndo).toBe(false);
|
||||
// expect(service.canRedo).toBe(true);
|
||||
|
||||
// expect(service.redo()).toBe('test');
|
||||
// expect(service.canUndo).toBe(true);
|
||||
// expect(service.redo()).toBe('test 2');
|
||||
// expect(service.redo()).toBe('test 3');
|
||||
|
||||
// expect(service.canRedo).toBe(false);
|
||||
|
||||
// expect(checkThrow(() => service.redo())).toBe(true);
|
||||
// }));
|
||||
|
||||
// it('should clear the redo stack when undoing', asyncTest(async () => {
|
||||
// const service = new UndoRedoService();
|
||||
|
||||
// service.push('test');
|
||||
// service.push('test 2');
|
||||
// service.push('test 3');
|
||||
|
||||
// service.undo();
|
||||
// expect(service.canRedo).toBe(true);
|
||||
|
||||
// service.push('test 4');
|
||||
// expect(service.canRedo).toBe(false);
|
||||
|
||||
// expect(service.undo()).toBe('test 4');
|
||||
// expect(service.undo()).toBe('test 2');
|
||||
// }));
|
||||
|
||||
// it('should limit the size of the undo stack', asyncTest(async () => {
|
||||
// const service = new UndoRedoService();
|
||||
|
||||
// for (let i = 0; i < 30; i++) {
|
||||
// service.push(`test${i}`);
|
||||
// }
|
||||
|
||||
// for (let i = 0; i < 20; i++) {
|
||||
// service.undo();
|
||||
// }
|
||||
|
||||
// expect(service.canUndo).toBe(false);
|
||||
// }));
|
||||
|
||||
// });
|
@@ -3,8 +3,8 @@
|
||||
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');
|
||||
const Setting = require('lib/models/Setting');
|
||||
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) => {
|
||||
@@ -50,7 +50,7 @@ describeIfCompatible('services_KeychainService', function() {
|
||||
}));
|
||||
|
||||
it('should save and load secure settings', asyncTest(async () => {
|
||||
Setting.setObjectKey('encryption.passwordCache', 'testing', '123456');
|
||||
Setting.setObjectValue('encryption.passwordCache', 'testing', '123456');
|
||||
await Setting.saveAll();
|
||||
await Setting.load();
|
||||
const passwords = Setting.value('encryption.passwordCache');
|
||||
|
@@ -9,7 +9,7 @@ const Resource = require('lib/models/Resource');
|
||||
const Note = require('lib/models/Note');
|
||||
const Tag = require('lib/models/Tag');
|
||||
const NoteTag = require('lib/models/NoteTag');
|
||||
const { shim } = require('lib/shim');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"spec_dir": "tests-build",
|
||||
"spec_files": [
|
||||
"*.js",
|
||||
"services/plugins/*.js",
|
||||
"!test-utils.js"
|
||||
],
|
||||
"stopSpecOnExpectationFailure": false,
|
||||
|
1
CliClient/tests/support/plugins/codemirror_test/dist/index.js
vendored
Normal file
1
CliClient/tests/support/plugins/codemirror_test/dist/index.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e){var n=this&&this.__assign||function(){return(n=Object.assign||function(t){for(var e,n=1,r=arguments.length;n<r;n++)for(var o in e=arguments[n])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t}).apply(this,arguments)},r=this&&this.__awaiter||function(t,e,n,r){return new(n||(n=Promise))((function(o,i){function u(t){try{a(r.next(t))}catch(t){i(t)}}function l(t){try{a(r.throw(t))}catch(t){i(t)}}function a(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(u,l)}a((r=r.apply(t,e||[])).next())}))},o=this&&this.__generator||function(t,e){var n,r,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function l(i){return function(l){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;u;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return u.label++,{value:i[1],done:!1};case 5:u.label++,r=i[1],i=[0];continue;case 7:i=u.ops.pop(),u.trys.pop();continue;default:if(!(o=u.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){u=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){u.label=i[1];break}if(6===i[0]&&u.label<o[1]){u.label=o[1],o=i;break}if(o&&u.label<o[2]){u.label=o[2],u.ops.push(i);break}o[2]&&u.ops.pop(),u.trys.pop();continue}i=e.call(t,u)}catch(t){i=[6,t],r=0}finally{n=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,l])}}};joplin.plugins.register({run:function(){return r(this,void 0,void 0,(function(){return o(this,(function(t){return joplin.filters.on("codeMirrorOptions",(function(t){return n(n({},t),{lineNumbers:!0})})),[2]}))}))}})}]);
|
9
CliClient/tests/support/plugins/codemirror_test/dist/manifest.json
vendored
Normal file
9
CliClient/tests/support/plugins/codemirror_test/dist/manifest.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"name": "To test setting preferences on CodeMirror editor",
|
||||
"version": "1.0.0",
|
||||
"homepage_url": "https://joplinapp.org",
|
||||
"permissions": [
|
||||
"model"
|
||||
]
|
||||
}
|
1
CliClient/tests/support/plugins/codemirror_test/global.d.ts
vendored
Normal file
1
CliClient/tests/support/plugins/codemirror_test/global.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare var joplin:any;
|
3858
CliClient/tests/support/plugins/codemirror_test/package-lock.json
generated
Normal file
3858
CliClient/tests/support/plugins/codemirror_test/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
CliClient/tests/support/plugins/codemirror_test/package.json
Normal file
18
CliClient/tests/support/plugins/codemirror_test/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "codemirror_test",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"ts-loader": "^7.0.5",
|
||||
"typescript": "^3.9.3",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
joplin.plugins.register({
|
||||
onStart: async function() {
|
||||
joplin.filters.on('codeMirrorOptions', (options:any) => {
|
||||
return { ...options, lineNumbers: true };
|
||||
});
|
||||
},
|
||||
});
|
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"noImplicitAny": true,
|
||||
"module": "es6",
|
||||
"target": "es5",
|
||||
"jsx": "react",
|
||||
"allowJs": true
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.ts',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: [ '.tsx', '.ts', '.js' ],
|
||||
},
|
||||
output: {
|
||||
filename: 'index.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
},
|
||||
};
|
2
CliClient/tests/support/plugins/dialog/.gitignore
vendored
Normal file
2
CliClient/tests/support/plugins/dialog/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
dist/*
|
||||
node_modules/
|
14
CliClient/tests/support/plugins/dialog/README.md
Normal file
14
CliClient/tests/support/plugins/dialog/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Joplin Plugin
|
||||
|
||||
This is a template to create a new Joplin plugin.
|
||||
|
||||
The main two files you will want to look at are:
|
||||
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user