1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-09-05 20:56:22 +02:00

Compare commits

..

252 Commits

Author SHA1 Message Date
Laurent Cozic
4693c924c3 Merge branch 'dev' into plugin_system 2020-10-09 18:33:38 +01:00
Laurent Cozic
833fb1264f Merge branch 'release-1.2' into dev 2020-10-09 18:33:27 +01:00
Laurent Cozic
6e7015e8f9 Fixed mobile build 2020-10-09 17:55:14 +01:00
Laurent Cozic
f007735936 ios-v10.2.0 2020-10-09 17:26:38 +01:00
Laurent Cozic
1f1cd9f11b Updated TOC plugin doc 2020-10-09 17:22:30 +01:00
Laurent Cozic
ac959b2882 Updated TOC plugin doc 2020-10-09 16:56:51 +01:00
Laurent Cozic
4609634259 Update website 2020-10-09 15:52:45 +01:00
Laurent Cozic
f06b64f3f9 Update TOC 2020-10-09 15:52:33 +01:00
Laurent Cozic
80503ad0c1 Updated links 2020-10-09 15:45:21 +01:00
Laurent Cozic
05dfaf7347 Replace links 2020-10-09 15:22:57 +01:00
Laurent Cozic
59be83d958 go back to absolute URLs as it is easier to grep 2020-10-09 15:15:44 +01:00
Laurent Cozic
e7676a148f Merge branch 'dev' into plugin_system 2020-10-09 15:09:55 +01:00
Laurent Cozic
73a39d36ea Update website 2020-10-09 14:58:06 +01:00
Laurent Cozic
a43ab26a46 Merge branch 'release-1.2' into dev 2020-10-09 14:57:44 +01:00
Laurent Cozic
f5f117cb72 Electron release v1.2.6 2020-10-09 12:17:54 +01:00
Laurent Cozic
fc6da04081 CLI v1.2.3 2020-10-09 12:17:40 +01:00
Laurent Cozic
12ff654986 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-10-09 12:10:16 +01:00
Laurent Cozic
e852ad846f Electron release v1.2.5 2020-10-09 12:10:06 +01:00
Laurent Cozic
cb28021a27 Provide more info when a revision cannot be created 2020-10-09 12:00:55 +01:00
Laurent Cozic
d8ab03f3bc Updating doc 2020-10-08 17:56:03 +01:00
Laurent Cozic
48b6b83950 Updating doc 2020-10-08 17:55:32 +01:00
Laurent Cozic
3e3bad0947 Fixed test plugin 2020-10-08 17:11:54 +01:00
Laurent Cozic
e527f590c5 Fixed plugin 2020-10-08 16:53:37 +01:00
Laurent Cozic
88f968aac5 Updated types 2020-10-08 16:52:22 +01:00
Laurent Cozic
bbd01c3a38 More API clean up 2020-10-08 16:39:20 +01:00
Laurent Cozic
e8d22a4177 Add command documentation 2020-10-08 15:52:41 +01:00
Laurent Cozic
6caec4df39 Refactored markdownUtils 2020-10-08 15:22:05 +01:00
Laurent Cozic
28e00fdf2e Android release v1.2.5 2020-10-08 12:56:12 +01:00
Laurent Cozic
3bd0656eab Android release v1.2.4 2020-10-08 12:51:48 +01:00
Laurent Cozic
e9af71dd76 Android: Reverted app to singleTop launch mode and fixed potential crash when sharing with app 2020-10-08 11:49:39 +01:00
Laurent Cozic
73b33e8e32 Android: Fixes #3800: Simplify initialisation code to prevent sharing
with app to create multiple instance of app and break settings.

Revert "Mobile: Add startup screen to show progress of db migration"

This reverts commit 569355a318.
2020-10-08 11:35:29 +01:00
Laurent Cozic
eea56fcf94 Added more plugin doc 2020-10-07 22:43:35 +01:00
Laurent Cozic
a5a278eced Version num 2020-10-07 21:08:02 +01:00
Laurent Cozic
a978ae4cfa Merge branch 'dev' into plugin_system 2020-10-07 21:05:39 +01:00
Laurent Cozic
c2c7efee91 Desktop: Also make toggle button area wider 2020-10-07 21:03:56 +01:00
Laurent Cozic
c9c44d5643 Merge branch 'release-1.2' into dev 2020-10-07 21:00:20 +01:00
Laurent Cozic
0836fca822 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-10-07 20:59:50 +01:00
Laurent Cozic
566df5039c Desktop: Fixes #3876: Notebooks and tags click area was too narrow 2020-10-07 20:58:43 +01:00
Laurent Cozic
dd1c1dded4 Update plugin types 2020-10-07 15:03:42 +01:00
Laurent Cozic
5407481976 fix 2020-10-07 12:33:42 +01:00
Laurent Cozic
5a1f6b13cf Fixed plugin update 2020-10-07 12:29:56 +01:00
Laurent Cozic
a904431782 Added way to update plugins 2020-10-07 12:28:25 +01:00
Laurent Cozic
b23ec936fd Deleted file 2020-10-07 10:15:51 +01:00
Laurent Cozic
73a4517902 More clean up on plugin doc 2020-10-07 10:14:52 +01:00
Laurent Cozic
a966b32583 Cleaned up plugin API to avoid depending on internal classes 2020-10-07 09:48:38 +01:00
Laurent Cozic
91a3428124 Rebuilt plugin doc 2020-10-06 21:30:33 +01:00
Laurent Cozic
93a5ba9490 Improved plugin doc 2020-10-06 21:30:05 +01:00
Laurent Cozic
e570f7a226 Disable filters for now 2020-10-06 18:23:15 +01:00
Laurent Cozic
9b28a8995f Open plugin dev tool window 2020-10-06 18:14:46 +01:00
Laurent Cozic
197f509f5d Increase version to 1.3 2020-10-06 14:04:21 +01:00
Laurent Cozic
559655bf33 Android release v1.2.3 2020-10-06 13:06:48 +01:00
Laurent Cozic
0eab23fbcf Android: Set app launchMode to singleInstance to try to fix lost settings issue 2020-10-06 13:02:41 +01:00
Laurent Cozic
f334f4f487 All: Improved handling of database migration failures 2020-10-06 12:47:33 +01:00
Laurent Cozic
4c83d7aa75 Fixed sidebar resize issue 2020-10-06 12:03:15 +01:00
Laurent Cozic
17e053b358 Handle module change event 2020-10-06 11:33:13 +01:00
Laurent Cozic
a29c93634d Converted locale file to TS 2020-10-06 10:27:43 +01:00
Laurent Cozic
a5f5bfcfec clean up 2020-10-06 10:16:18 +01:00
Laurent Cozic
b509329383 Convert interopservicehelper to TS 2020-10-06 10:14:54 +01:00
Laurent Cozic
91c7abed42 Added back support for keymap on command service 2020-10-06 09:55:23 +01:00
Laurent Cozic
54fda6ac97 Refactored menu bar 2020-10-05 19:29:53 +01:00
Laurent Cozic
341eefebaf Converted BaseApplication to TypeScripy 2020-10-05 14:44:56 +01:00
Laurent Cozic
af714cbdac Optimize command state handling 2020-10-05 13:20:23 +01:00
Laurent Cozic
6a0bf15c28 Clean up 2020-10-03 18:24:44 +01:00
Laurent Cozic
5a2bdad348 Cleaned up toolbar code to improve rendering 2020-10-03 18:22:39 +01:00
Laurent Cozic
fd08bfdd86 Better way to create buttonToolbarInfos 2020-10-03 17:49:28 +01:00
Laurent Cozic
1a5cead659 Added @typescript-eslint/explicit-member-accessibility rule 2020-10-03 15:45:32 +01:00
Laurent Cozic
85df133386 Added command service tests and a way to get multiple toolbar buttons 2020-10-03 15:36:23 +01:00
Laurent Cozic
869d11e113 Added way to parse when-clauses for commands 2020-10-03 14:40:12 +01:00
Laurent Cozic
d7a01d3965 Fixed issue with state that was accidentally mutated 2020-10-02 20:06:52 +01:00
Laurent Cozic
989036241d Fixed toolbar button label 2020-10-02 20:03:14 +01:00
Laurent Cozic
433cef1827 Fixed encryption config screen password save logic 2020-10-02 19:59:36 +01:00
Laurent Cozic
433d34f62b Resize app content when banner is added on top 2020-10-02 19:40:12 +01:00
Laurent Cozic
e7ec33bbf9 Added event tests 2020-10-02 18:48:25 +01:00
Laurent Cozic
a29f42d78d Converted synchronizer to TypeScript 2020-10-02 18:03:29 +01:00
Laurent Cozic
74ed234ab9 Added support for onAlarmTrigger event 2020-10-02 17:41:18 +01:00
over-soul
49bfa49489 All: Translation: Update fa.po (#3856)
Updated some existing Persian translations and added some new translations.

Co-authored-by: over-soul <ali@elego.com>
2020-10-02 12:06:30 -04:00
Paweł Żukowski
5f81944a3e All: Translation: Update pl_PL.po (#3855)
Translate missing strings and fix few existing typos.
2020-10-02 12:05:10 -04:00
Laurent Cozic
86b76ccb77 Fixed setting plugin 2020-10-02 16:49:39 +01:00
Laurent Cozic
29aedf8480 Fixed toc demo 2020-10-02 16:21:32 +01:00
Laurent Cozic
9486f5e0d2 Simplify plugin 2020-10-02 16:07:04 +01:00
Laurent Cozic
9a458431b8 Fixed sandbox proxy namespace logic 2020-10-02 15:56:34 +01:00
Laurent Cozic
2c9db9d18c Fixed dialog plugin API 2020-10-02 15:21:58 +01:00
Laurent Cozic
ae9c535842 Improved setting API 2020-10-02 13:02:39 +01:00
Laurent Cozic
a518da587e Fixed demo 2020-10-02 12:52:05 +01:00
Laurent Cozic
92e6e00d9e Fixed commands 2020-10-02 12:49:40 +01:00
Laurent Cozic
b64c9cf18a Finished refactoring interop service 2020-10-02 12:42:25 +01:00
Laurent Cozic
275d6e230d Converted shim to TypeScript 2020-10-02 11:38:04 +01:00
Laurent Cozic
ab8ce15c33 Fixed command api 2020-10-02 10:42:03 +01:00
Laurent Cozic
3fb6179587 lonter 2020-10-02 01:03:39 +01:00
Laurent Cozic
28cc38064c Fixed interop plugin API to work with multi-process arch and cleaned up interop service 2020-10-02 00:44:42 +01:00
Laurent Cozic
1fa5ab2b96 Refactoring and got ipc messages to work 2020-10-01 23:42:49 +01:00
Laurent Cozic
15f4e635d9 Minor tweaks 2020-10-01 15:10:59 +01:00
Laurent Cozic
7a79d7ef7e Refactoring and got ipc messages to work 2020-10-01 14:47:38 +01:00
Laurent Cozic
776e7dfe3f renaming logger 2020-10-01 10:31:01 +01:00
Laurent Cozic
790b622cbc Updated doc 2020-09-30 23:38:28 +01:00
Laurent Cozic
89117b4ee9 Renamed 2020-09-30 23:36:27 +01:00
Laurent Cozic
c245517e0f Renamed to PlatformImplementation 2020-09-30 23:31:27 +01:00
Laurent Cozic
31db95d0c4 Cleaned up plugin API names 2020-09-30 23:17:18 +01:00
Laurent Cozic
2cd50de065 Moved plugin classes under /plugins namespace 2020-09-30 23:07:46 +01:00
Laurent Cozic
6dcb7e2605 Added doc 2020-09-30 17:19:34 +01:00
Laurent Cozic
9c9bd4ba51 Changed plugin system architecture to allow using one process per plugin 2020-09-30 16:56:41 +01:00
Laurent Cozic
71e6964945 Added proxy class 2020-09-30 10:24:15 +01:00
Laurent Cozic
00057da17d Electron release v1.2.4 2020-09-30 08:16:46 +01:00
Laurent Cozic
0a05464013 Desktop: Regression: Context menu on sidebar did not work anymore 2020-09-30 08:16:20 +01:00
Laurent Cozic
97dc2fa6bd Fixed tests 2020-09-29 16:42:32 +01:00
Laurent Cozic
161e112e7b Added support for getting selected notes and adding a context menu item 2020-09-29 16:28:25 +01:00
Laurent Cozic
c93a6f86cd Added way to add a custom Markdown plugin 2020-09-29 15:29:11 +01:00
Laurent Cozic
9bb178b9d9 Fixed broken merge 2020-09-29 15:28:12 +01:00
Laurent Cozic
8087bc5280 Merge branch 'dev' into plugin_system 2020-09-29 14:30:33 +01:00
Laurent Cozic
26f5a606e0 Merge branch 'release-1.2' into dev 2020-09-29 14:29:38 +01:00
Laurent Cozic
9ebb574059 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-09-29 14:27:33 +01:00
Laurent Cozic
d29c3c2466 Desktop: Regression: Sidebar toggle button did not work anymore 2020-09-29 14:26:05 +01:00
Laurent Cozic
a71f1c19ec Android release v1.2.2 2020-09-29 12:40:46 +01:00
Laurent Cozic
485921d879 CLI v1.2.2 2020-09-29 12:34:42 +01:00
Laurent Cozic
15de7572c0 Electron release v1.2.3 2020-09-29 12:32:24 +01:00
Laurent Cozic
09f41dd50e Desktop: Make global search field wider when it has focus 2020-09-29 12:31:19 +01:00
Laurent Cozic
7b8ee467a0 Desktop: Improved rendering of All Notes item in sidebar 2020-09-29 11:49:51 +01:00
Laurent Cozic
99a496d684 Desktop: Always label "Click to add tags" 2020-09-29 11:33:22 +01:00
Laurent Cozic
100aaab58d Refactor reducer to TypeScript and using immerjs 2020-09-29 11:16:01 +01:00
Laurent Cozic
126c7b5a75 Merge branch 'dev' into reducer_refactor 2020-09-29 11:00:31 +01:00
Laurent Cozic
d448ea3a02 Merge branch 'dev' into plugin_system 2020-09-29 10:59:55 +01:00
Laurent Cozic
9d6975a9e2 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-09-29 10:57:34 +01:00
Laurent Cozic
555727e5fe Refactor reducer 2020-09-29 10:56:33 +01:00
Laurent Cozic
f43ee123d8 Tools: Fixed tests 2020-09-29 10:54:31 +01:00
Laurent Cozic
f42fb1b871 Changed tag label 2020-09-29 10:51:47 +01:00
Laurent Cozic
cf2442c5b2 Desktop: Fixes #3835: Prevent crash in rare case when opening the config screen 2020-09-29 08:40:14 +01:00
Laurent Cozic
e0e4735b03 Desktop: Fixes #3754: Refresh search results when searching by tag and when a tag is changed 2020-09-29 08:11:52 +01:00
osso73
138faa2aae All: Translation: Update ca.po (#3844) 2020-09-29 02:06:23 -04:00
Laurent Cozic
8bd58c9608 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-09-28 19:19:52 +01:00
Laurent Cozic
215a725ded Mobile: Fixes #3834: Fixed search highlights 2020-09-28 19:19:21 +01:00
Naveen M V
12c0a05af0 Desktop: Keep search fuzzy scores between 0 and 2 (#3812) 2020-09-28 18:58:19 +01:00
Caleb John
a7fa119041 Desktop: Extend functionality of codemirror vim (#3823)
add swapLine(Up/Down)
have `o` use the more complex list indent
enable sync initializing from vim (and maybe emacs)
split keymap stuff into it's own file
2020-09-28 18:57:17 +01:00
Laurent Cozic
7fb52b8b0e Desktop: Fix issue with highlighted search terms in CodeMirror viewer 2020-09-28 18:44:21 +01:00
Laurent Cozic
3e86ae4a82 Desktop: Disable fuzzy search for now due to performance issues 2020-09-28 18:41:16 +01:00
Laurent Cozic
77eceea426 Ensure plugin settings are within their own namespaces 2020-09-28 18:11:53 +01:00
Laurent Cozic
a09c6f152c Added support for plugin dialogs 2020-09-28 17:26:22 +01:00
Laurent Cozic
3830195752 Allow creating new section from plugin 2020-09-27 13:45:08 +01:00
Laurent Cozic
c9594065c3 Refactor Settings 2020-09-27 13:31:45 +01:00
Laurent Cozic
360d3bbff9 Allow creating new settings from plugin 2020-09-27 13:03:37 +01:00
Laurent Cozic
6fde8dfe52 Refactored Settings into TypeScript 2020-09-26 18:14:00 +01:00
Laurent Cozic
de2ccfbfe0 Added explanation for shim timers and implemented RN side 2020-09-26 12:42:44 +01:00
Laurent Cozic
31f53b12fd Move timers to shim 2020-09-26 12:19:13 +01:00
Laurent Cozic
d45b280ada Done text selection plugin 2020-09-25 11:18:06 +01:00
Ji-Hyeon Gim
ca46590ff3 All: Translation: Update ko.po (#3813)
Signed-off-by: Ji-Hyeon Gim <potatogim@potatogim.net>
2020-09-24 21:17:53 -04:00
Laurent Cozic
b5a137545e Add support getting and replacing editor selection 2020-09-24 18:35:20 +01:00
Laurent Cozic
4e80dbb7a7 Allow tagging desktop-only feature in plugin doc 2020-09-24 15:53:37 +01:00
Laurent Cozic
90b0c99806 Merge branch 'release-1.2' into plugin_system 2020-09-24 14:50:20 +01:00
Laurent Cozic
947d81d96d Desktop: Optimised sidebar rendering speed 2020-09-24 14:30:20 +01:00
Laurent Cozic
6ca640d2ed Desktop: Fix: Fade out checked items in Rich Text editor too 2020-09-23 17:49:25 +01:00
Laurent Cozic
c8c0c3af46 Changed to node-slug 2020-09-23 17:34:58 +01:00
Laurent Cozic
110de50bf9 Allow setting custom shortcuts and saving/loading them 2020-09-23 17:26:30 +01:00
Laurent Cozic
b7e110d888 Converted eventManager to TypeScript 2020-09-23 16:25:00 +01:00
Laurent Cozic
f1c557cb43 Converted app to TypeScript 2020-09-23 15:51:31 +01:00
Laurent Cozic
43e9fc92c9 Adding support for custom menu items 2020-09-23 15:24:42 +01:00
Laurent Cozic
10fa331731 Define plugin state types 2020-09-23 15:18:45 +01:00
Laurent Cozic
cc8e122de3 Added support for custom commands and toolbar buttons 2020-09-23 15:10:31 +01:00
Laurent Cozic
bca5fd8db9 gitignore 2020-09-23 14:10:02 +01:00
Laurent Cozic
13101f7d9b Merge branch 'dev' into plugin_system 2020-09-23 14:09:21 +01:00
Laurent Cozic
6aca233b21 CLI v1.2.1 2020-09-23 12:16:58 +01:00
Laurent Cozic
2200be697e Cli: Fixed crash due to missing spellfix extension 2020-09-23 12:14:17 +01:00
Laurent Cozic
25ab3c323b Desktop: Fixes #3801: Fixed editor font size 2020-09-23 11:39:36 +01:00
Laurent Cozic
5bf30a9586 Merge branch 'release-1.2' into dev 2020-09-23 10:24:55 +01:00
Laurent Cozic
b6779a8074 Desktop: Fixes #3810: Only disable relevant toolbar buttons when editor is read-only 2020-09-23 10:21:24 +01:00
Caleb John
59599d318c Desktop: Adjust the codemirror code block colors for the dark theme (#3794) 2020-09-23 09:34:39 +01:00
Arda Kılıçdağı
538600fd6c All: Translation: Update tr_TR.po (#3798) 2020-09-22 21:12:31 -04:00
Ji-Hyeon Gim
63264ba471 All: Translation: Update ko.po (#3778)
This patch includes the translation of missing strings, the improvement of the existing translation

Signed-off-by: Ji-Hyeon Gim <potatogim@potatogim.net>
2020-09-22 21:11:55 -04:00
Laurent Cozic
95e7f3df7d Electron release v1.2.2 2020-09-22 16:39:18 +01:00
Laurent Cozic
366fd2a333 Fixed desktop build 2020-09-22 16:38:47 +01:00
Laurent Cozic
5be99a4a16 Merge branch 'release-1.2' of github.com:laurent22/joplin into release-1.2 2020-09-22 16:37:23 +01:00
Laurent Cozic
d86f6a1fbd Tools: Require setting type flag for new Android releases 2020-09-22 16:36:46 +01:00
Laurent Cozic
4f2884a0f7 Started adding support for registering commands 2020-09-21 11:38:09 +01:00
Laurent Cozic
4872f1419c Also add placeholder for JSON import 2020-09-20 16:57:17 +01:00
Laurent Cozic
fdcaab3caf Got JSON export working as a plugin 2020-09-20 16:19:37 +01:00
Laurent Cozic
9f2c4b938f Added complete lib to plugin doc 2020-09-20 15:36:30 +01:00
Laurent Cozic
8be65acf7d Testing interop plugin 2020-09-20 12:09:32 +01:00
Laurent Cozic
e05aa433e4 Allow creating custom exporters 2020-09-19 15:50:46 +01:00
Laurent Cozic
ccfb0b43d6 Refactor 2020-09-19 14:56:49 +01:00
Laurent Cozic
4211e962c6 Merge branch 'release-1.2' into plugin_system 2020-09-19 14:22:24 +01:00
Laurent Cozic
6b54c4244b Refactored 2020-09-19 14:19:09 +01:00
Laurent Cozic
1d5a4bd381 Simplified interop interface 2020-09-19 12:20:01 +01:00
Laurent Cozic
86a1103a64 Remove JSON exporter 2020-09-19 11:13:49 +01:00
Laurent Cozic
45edaaa96f Converted interop service to TypeScript 2020-09-19 11:04:29 +01:00
Laurent Cozic
b7b158aa94 Fixed doc title 2020-09-18 15:53:25 +01:00
Laurent Cozic
e6bc55b6f8 Update plugin doc 2020-09-18 15:46:25 +01:00
Laurent Cozic
111092791c Updated plugin doc 2020-09-18 13:10:47 +01:00
Laurent Cozic
4e91e01ddc Updated plugin doc 2020-09-18 13:08:01 +01:00
Laurent Cozic
44dce6c6c3 Fixed frozen state issue 2020-09-18 10:10:26 +01:00
Laurent Cozic
b25ad50a1b Add more doc 2020-09-18 09:59:22 +01:00
Laurent Cozic
e2e3be66ee doc 2020-09-17 18:02:57 +01:00
Laurent Cozic
4b3119ebba Finished tutorial 2020-09-17 17:39:15 +01:00
Laurent Cozic
1712a67e2e Doc draft 2020-09-17 16:19:25 +01:00
Laurent Cozic
cd563b050c Bottom border on user views 2020-09-17 15:41:05 +01:00
Laurent Cozic
4426f2dbec Make sure plugin views can be resized 2020-09-17 15:08:43 +01:00
Laurent Cozic
0fbbf2eee0 Remember plugin view sizes 2020-09-17 14:51:50 +01:00
Laurent Cozic
2fdad2fe80 Make sure user views have a stable ID 2020-09-17 09:22:03 +01:00
Laurent Cozic
0249ff48ca Removed obsolete handlers 2020-09-17 08:51:12 +01:00
Laurent Cozic
142fc02f9c Simplified UserWebview component 2020-09-16 17:57:30 +01:00
Laurent Cozic
842b123285 Fixed slub 2020-09-16 17:30:39 +01:00
Laurent Cozic
a4aca68b85 Support for theme in webview 2020-09-16 17:27:13 +01:00
Laurent Cozic
1397af0692 User webviews 2020-09-16 16:19:33 +01:00
Laurent Cozic
5da760dd0c Added a way to load a plugin for development 2020-09-15 17:49:43 +01:00
Laurent Cozic
511d58d3af Various improvements 2020-09-15 17:02:02 +01:00
Laurent Cozic
a1c9e675ad Improve plugin build 2020-09-15 16:56:48 +01:00
Laurent Cozic
0349ad0b80 Merge branch 'release-1.2' into plugin_system 2020-09-15 14:41:47 +01:00
Laurent Cozic
9d8411a25e Add TOC plugin demo 2020-09-15 13:47:47 +01:00
Laurent Cozic
754ba2267a Merge branch 'dev' into plugin_system 2020-09-15 13:41:57 +01:00
Laurent Cozic
4cdac308d1 Wraps console calls 2020-09-15 10:36:32 +01:00
Laurent Cozic
c0d5c7c282 Merge branch 'dev' into plugin_system 2020-09-14 14:06:21 +01:00
Laurent
f9296992bf Merge branch 'dev' into plugin_system 2020-08-01 18:58:08 +01:00
Laurent Cozic
5b06ebde1e Updated 2020-08-01 18:38:43 +01:00
Laurent Cozic
d309c75974 Merge branch 'dev' into plugin_system 2020-08-01 18:35:05 +01:00
Laurent Cozic
807c89a42f Added way to get dev mode command line 2020-07-05 18:55:21 +01:00
Laurent Cozic
0b8350e9ea Adding plugin doc 2020-07-05 17:58:24 +01:00
Laurent Cozic
49e7be8924 Ignored files 2020-07-05 17:24:20 +01:00
Laurent Cozic
810c63e3b2 Update doc 2020-07-04 18:38:12 +01:00
Laurent Cozic
d917ca5551 Added plugin doc auto-generation 2020-07-04 18:27:47 +01:00
Laurent Cozic
ec642300ab Moved sandbox to sub-folder 2020-07-04 17:56:21 +01:00
Laurent Cozic
9034d646bf Moved sandbox to a class 2020-07-04 17:02:32 +01:00
Laurent Cozic
96f6bbb035 Allow executing commands from plugin 2020-07-04 16:05:02 +01:00
Laurent Cozic
e14ed655d2 Freeze state in dev mode 2020-07-04 15:32:24 +01:00
Laurent Cozic
54e5323f54 Fixed another issue due to modifying state data 2020-07-04 15:24:53 +01:00
Laurent Cozic
ef58affed1 Fix tests 2020-07-04 15:09:14 +01:00
Laurent Cozic
76fa87d878 Fixed test issue due modification of immutable state 2020-07-04 14:52:55 +01:00
Laurent Cozic
2db2225788 Merge branch 'master' into plugin_system 2020-07-04 14:31:54 +01:00
Laurent Cozic
425c1763f4 Desktop: Fixed GotoAnything rendering issue with HTML notes 2020-07-04 12:57:19 +01:00
Laurent Cozic
044f2eac6a Improved view support 2020-06-28 17:10:34 +01:00
Laurent Cozic
281f135125 Improved view support 2020-06-28 17:08:38 +01:00
Laurent Cozic
6c88f8b8ae Merge branch 'plugin_system' of github.com:laurent22/joplin into plugin_system 2020-06-28 16:57:28 +01:00
Laurent Cozic
832abcddf0 Add support for state watch 2020-06-27 11:54:42 +01:00
Laurent Cozic
e6c481f45c Fixed tests 2020-06-27 01:05:40 +01:00
Laurent Cozic
11fecfb83a Cleaned up naming and types 2020-06-26 23:03:20 +01:00
Laurent Cozic
2facc9868e Renamed control to view 2020-06-26 22:52:40 +01:00
Laurent Cozic
7b9ad9d1c3 Moved listener to view itself 2020-06-26 22:46:45 +01:00
Laurent Cozic
3b96a99f3e Allow sending messages from webview script to plugin 2020-06-26 18:13:00 +01:00
Laurent Cozic
575ce5128b Added reducer 2020-06-26 16:14:59 +01:00
Laurent Cozic
dece28da35 Better integration of custom webviews 2020-06-25 22:15:31 +01:00
Laurent Cozic
2ffc429971 Merge branch 'master' into plugin_system 2020-06-25 20:27:38 +01:00
Laurent Cozic
8baa125842 Refactored to save plugin state in Redux store 2020-06-25 20:25:50 +01:00
Laurent Cozic
6b6092ffc7 Merge branch 'master' into plugin_system 2020-06-24 23:14:16 +01:00
Laurent Cozic
714c912aff Added support for plugin webview 2020-06-24 23:10:19 +01:00
Laurent Cozic
ebf8b744e1 Tools: Fixed build issues 2020-06-24 16:33:35 +01:00
Laurent Cozic
1039e98396 Only load plugins if dir present 2020-06-23 17:25:35 +01:00
Laurent Cozic
8f00538cb1 Merge branch 'master' into plugin_system 2020-06-22 23:07:12 +01:00
Laurent Cozic
2b530a3ff9 Merge branch 'master' into plugin_system 2020-06-21 21:37:58 +00:00
Laurent Cozic
d089511aa6 Added support filters and custom views 2020-06-21 21:30:07 +00:00
Laurent Cozic
450c8dbf22 Added support for setting and getting runtime preferences and done CodeMirror plugin test 2020-06-18 00:49:32 +01:00
Laurent Cozic
94d87285dc Merge branch 'master' into plugin_system 2020-06-17 23:50:12 +01:00
Laurent Cozic
ffeb7d0ecd Add support for TypeScript in plugins 2020-05-25 18:04:15 +01:00
Laurent Cozic
aba92857cb Load plugins from directory 2020-05-25 17:28:32 +01:00
Laurent Cozic
5918c81dbb Merge branch 'master' into plugin_system 2020-05-25 16:56:04 +01:00
Laurent Cozic
819d9fd977 Added more tests 2020-05-23 10:40:10 +01:00
Laurent Cozic
ad80e074de Started plugin system 2020-05-21 23:51:51 +00:00
826 changed files with 98520 additions and 7826 deletions

View File

@@ -59,15 +59,25 @@ 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/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 +113,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
@@ -119,6 +130,7 @@ ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
@@ -137,7 +149,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
@@ -145,6 +157,7 @@ ElectronClient/gui/NoteList/NoteList.js
ElectronClient/gui/NoteListControls/commands/focusSearch.js
ElectronClient/gui/NoteListControls/NoteListControls.js
ElectronClient/gui/NoteListItem.js
ElectronClient/gui/NoteTextViewer.js
ElectronClient/gui/NoteToolbar/NoteToolbar.js
ElectronClient/gui/OneDriveLoginScreen.js
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
@@ -152,6 +165,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
@@ -164,33 +178,110 @@ ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
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/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
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/markdownUtils.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/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/api/types.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
ReactNativeClient/lib/services/rest/Api.js
ReactNativeClient/lib/services/rest/errors.js
ReactNativeClient/lib/services/searchengine/filterParser.js
ReactNativeClient/lib/services/searchengine/queryBuilder.js
@@ -204,6 +295,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
@@ -214,6 +307,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

View File

@@ -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'],
},
},
],
};

99
.gitignore vendored
View File

@@ -52,15 +52,26 @@ Tools/commit_hook.txt
*.map
ReactNativeClient/lib/sql-extensions/spellfix.so
ReactNativeClient/lib/sql-extensions/spellfix.dylib
CliClient/build/
plugin_types/
# 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/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 +107,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
@@ -112,6 +124,7 @@ ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
@@ -130,7 +143,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
@@ -138,6 +151,7 @@ ElectronClient/gui/NoteList/NoteList.js
ElectronClient/gui/NoteListControls/commands/focusSearch.js
ElectronClient/gui/NoteListControls/NoteListControls.js
ElectronClient/gui/NoteListItem.js
ElectronClient/gui/NoteTextViewer.js
ElectronClient/gui/NoteToolbar/NoteToolbar.js
ElectronClient/gui/OneDriveLoginScreen.js
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
@@ -145,6 +159,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
@@ -157,33 +172,110 @@ ElectronClient/gui/style/StyledInput.js
ElectronClient/gui/style/StyledTextInput.js
ElectronClient/gui/ToggleEditorsButton/styles/index.js
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/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
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/markdownUtils.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/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/api/types.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
ReactNativeClient/lib/services/rest/Api.js
ReactNativeClient/lib/services/rest/errors.js
ReactNativeClient/lib/services/searchengine/filterParser.js
ReactNativeClient/lib/services/searchengine/queryBuilder.js
@@ -197,6 +289,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
@@ -207,6 +301,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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -96,4 +96,4 @@ The Markdown renderer is located under ReactNativeClient/lib/joplin-renderer. Wh
# Troubleshooting
Please read for the [Build Troubleshooting Document](https://github.com/laurent22/joplin/blob/master/readme/build_troubleshooting.md) for various tips on how to get the build working.
Please read for the [Build Troubleshooting Document](https://github.com/laurent22/joplin/blob/dev/readme/build_troubleshooting.md) for various tips on how to get the build working.

View File

@@ -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');

View File

@@ -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) {

View File

@@ -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);

View File

@@ -1,4 +1,4 @@
const { _ } = require('lib/locale.js');
const { _ } = require('lib/locale');
const { reg } = require('lib/registry.js');
class BaseCommand {

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 = {};

View File

@@ -3,7 +3,7 @@ const BaseItem = require('lib/models/BaseItem');
const BaseModel = require('lib/BaseModel');
const { toTitleCase } = require('lib/string-utils.js');
const { reg } = require('lib/registry.js');
const markdownUtils = require('lib/markdownUtils');
const markdownUtils = require('lib/markdownUtils').default;
const { Database } = require('lib/database.js');
class Command extends BaseCommand {
@@ -53,9 +53,9 @@ class Command extends BaseCommand {
const lines = [];
lines.push('# Joplin API');
lines.push('# Joplin Data API');
lines.push('');
lines.push('This API is available when the clipper server is running. It provides access to the notes, notebooks, tags and other Joplin object via a REST API. Plugins can also access this API even when the clipper server is not running.');
lines.push('');
lines.push('In order to use it, you\'ll first need to find on which port the service is running. To do so, open the Web Clipper Options in Joplin and if the service is running it should tell you on which port. Normally it runs on port **41184**. If you want to find it programmatically, you may follow this kind of algorithm:');
lines.push('');

View File

@@ -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() {

View File

@@ -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');

View File

@@ -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() {

View File

@@ -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');

View File

@@ -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');

View File

@@ -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;
};

View File

@@ -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 {

View File

@@ -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() {

View File

@@ -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');

View File

@@ -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));

View File

@@ -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');

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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');

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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() {

View File

@@ -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 {

View File

@@ -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');

View File

@@ -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 {

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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 {

View File

@@ -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() {

View File

@@ -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');

View File

@@ -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() {

View File

@@ -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() {

View File

@@ -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 = ' ';

View File

@@ -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');

View 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;
}
}
}

View File

@@ -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`);
},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Joplin-CLI 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Last-Translator: Ji-Hyeon Gim <potatogim@potatogim.net>\n"
"Language-Team: \n"
"Language: ko\n"
"MIME-Version: 1.0\n"
@@ -122,7 +122,7 @@ msgstr "생성됨: %d."
#: CliClient/app/command-import.js:49 ElectronClient/gui/ImportScreen.min.js:71
#, javascript-format
msgid "Updated: %d."
msgstr "업데이트됨: %d."
msgstr "갱신됨: %d."
#: CliClient/app/command-import.js:50 ElectronClient/gui/ImportScreen.min.js:72
#, javascript-format
@@ -312,7 +312,7 @@ msgstr "지정된 대상으로 동기화 합니다 (기본값은 sync.target con
#: CliClient/app/command-sync.js:35
msgid "Upgrade the sync target to the latest version."
msgstr ""
msgstr "동기화 대상을 최신 버전으로 업그레이드합니다."
#: CliClient/app/command-sync.js:81 CliClient/app/command-sync.js:95
#: ElectronClient/gui/OneDriveLoginScreen.min.js:40
@@ -724,7 +724,7 @@ msgstr "노트와 노트북에 관한 요약 정보를 표시합니다."
msgid ""
"To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`"
msgstr ""
"항목들을 다시 복호화하라면 `e2ee decrypt --retry-failed-items`를 실행합니다."
"항목들을 다시 복호화하라면 `e2ee decrypt --retry-failed-items`를 실행합니다"
#: CliClient/app/command-tag.js:14
msgid ""
@@ -794,7 +794,7 @@ msgstr "취소"
#: ElectronClient/bridge.js:198
msgid ""
"The app is now going to close. Please relaunch it to complete the process."
msgstr ""
msgstr "애플리케이션이 곧 종료됩니다. 프로세스를 완료하려면 다시 실해주세요."
#: ElectronClient/plugins/GotoAnything.min.js:446
msgid ""
@@ -1154,13 +1154,13 @@ msgstr "%s 새로 만들기..."
#: ElectronClient/gui/NoteEditor/NoteEditor.js:344
msgid "The following attachments are being watched for changes:"
msgstr ""
msgstr "다음 첨부 파일들이 변경되었는지 감시하고 있습니다:"
#: ElectronClient/gui/NoteEditor/NoteEditor.js:347
msgid ""
"The attachments will no longer be watched when you switch to a different "
"note."
msgstr ""
msgstr "다른 노트로 전환하면 첨부 파일이 더 이상 감시되지 않습니다."
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:25
msgid "Select all"
@@ -1189,7 +1189,7 @@ msgstr "코드"
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:55
#: ElectronClient/gui/NoteText.min.js:1738
msgid "Numbered List"
msgstr "숫자가 매겨진 목록"
msgstr "번호 매기기 목록"
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:60
#: ElectronClient/gui/NoteText.min.js:1746
@@ -1199,7 +1199,7 @@ msgstr "글머리 기호 목록"
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:65
#: ElectronClient/gui/NoteText.min.js:1754
msgid "Checkbox"
msgstr "체크박스"
msgstr "확인 상자"
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:70
#: ElectronClient/gui/NoteText.min.js:1762
@@ -1228,7 +1228,7 @@ msgstr "노트 본문"
#: ElectronClient/gui/EncryptionConfigScreen.min.js:163
#: ElectronClient/gui/ResourceScreen.js:38
msgid "ID"
msgstr "ID"
msgstr "식별자"
#: ElectronClient/gui/NotePropertiesDialog.min.js:27
msgid "Created"
@@ -1236,7 +1236,7 @@ msgstr "생성됨"
#: ElectronClient/gui/NotePropertiesDialog.min.js:28
msgid "Updated"
msgstr "업데이트됨"
msgstr "갱신됨"
#: ElectronClient/gui/NotePropertiesDialog.min.js:29
msgid "Completed"
@@ -1271,7 +1271,7 @@ msgstr "노트 속성"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:62
msgid "An unexpected error occured while importing the keymap!"
msgstr ""
msgstr "키맵을 가져오는 중에 예기치 못한 오류가 발생했습니다!"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:119
#: ElectronClient/gui/MainScreen/MainScreen.min.js:437
@@ -1310,7 +1310,7 @@ msgstr "실제 크기"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:22
#: ElectronClient/app.js:868
msgid "Website and documentation"
msgstr "웹사이트 및 각종 문서"
msgstr "웹사이트 및 참고 문서"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:24
msgid "Hide Joplin"
@@ -1354,6 +1354,9 @@ msgid ""
"may take a few minutes to complete and the app needs to be restarted. To "
"proceed please click on the link."
msgstr ""
"Joplin이 동기화를 하기에 앞서 동기화 대상의 업그레이드가 필요합니다. 작업이 "
"완료되기 위해서 몇 분 정도 걸릴 수 있으며, 앱을 다시 시작해야 합니다. 계속하"
"려면 링크를 눌러주세요."
#: ElectronClient/gui/MainScreen/MainScreen.min.js:306
msgid "Restart and upgrade"
@@ -2000,6 +2003,8 @@ msgid ""
"notes. Please be careful when deleting one of them as they cannot be "
"restored afterwards."
msgstr ""
"노트에 링크된 첨부 파일을 보여주는 고급 도구입니다. 여기에서 보여지는 항목을 "
"삭제할 경우, 나중에 복원할 수 없으므로 주의하시기 바랍니다."
#: ElectronClient/gui/ResourceScreen.js:140
msgid "Please wait..."
@@ -2210,6 +2215,8 @@ msgid ""
"You are about to attach a large image (%dx%d pixels). Would you like to "
"resize it down to %d pixels before attaching it?"
msgstr ""
"크기가 큰 이미지(%dx%d 픽셀)를 첨부하려고 합니다. 첨부하기 전에 크기를 %d 픽"
"셀로 줄이시겠습니까?"
#: ReactNativeClient/lib/shim-init-node.js:157
#, javascript-format
@@ -2224,7 +2231,7 @@ msgstr "제목"
#: ReactNativeClient/lib/models/Folder.js:28
#: ReactNativeClient/lib/models/Note.js:26
msgid "updated date"
msgstr "업데이트된 날짜"
msgstr "수정 날짜"
#: ReactNativeClient/lib/models/Folder.js:88
msgid "Conflicts"
@@ -2578,16 +2585,16 @@ msgstr "Joplin 앱에 전역적으로 적용되는 사용자 정의 스타일시
#: ReactNativeClient/lib/models/Setting.js:598
msgid "Automatically update the application"
msgstr "자동으로 업데이트 하기"
msgstr "자동으로 업데이트하기"
#: ReactNativeClient/lib/models/Setting.js:599
msgid "Get pre-releases when checking for updates"
msgstr "업데이트 시 프리-릴리즈 받기"
msgstr "사전-출시 버전일 경우에도 업데이트"
#: ReactNativeClient/lib/models/Setting.js:599
#, javascript-format
msgid "See the pre-release page for more details: %s"
msgstr "자세한 내용은 프리-릴리즈 페이지를 참조해주세요: %s"
msgstr "자세한 내용은 사전-출시 페이지를 참조해주세요: %s"
#: ReactNativeClient/lib/models/Setting.js:607
msgid "Synchronisation interval"
@@ -2653,7 +2660,7 @@ msgstr "Legal"
#: ReactNativeClient/lib/models/Setting.js:636
msgid "Page orientation for PDF export"
msgstr "PDF를 내보낼때의 페이지 방향"
msgstr "PDF를 내보낼 때의 페이지 방향"
#: ReactNativeClient/lib/models/Setting.js:638
msgid "Portrait"
@@ -2701,14 +2708,14 @@ msgstr "TLS 인증서 오류 무시"
#: ReactNativeClient/lib/models/Setting.js:692
msgid "Fail-safe"
msgstr "안전 작동"
msgstr "안전 장치"
#: ReactNativeClient/lib/models/Setting.js:693
msgid ""
"Fail-safe: Do not wipe out local data when sync target is empty (often the "
"result of a misconfiguration or bug)"
msgstr ""
"안전 장치: 동기화 목표가 비어 있을 경우, 로컬 데이터를 지우마세요 (종종 "
"안전 장치: 동기화할 대상이 비어 있다면, 로컬 데이터를 지우지 않습니다. (종종 "
"잘못된 설정이나 버그로 인해 발생됩니다)"
#: ReactNativeClient/lib/models/Setting.js:697
@@ -2716,12 +2723,12 @@ msgid ""
"Specify the port that should be used by the API server. If not set, a "
"default will be used."
msgstr ""
"API 서버 사용할 포트를 선택해주세요. 선택되지 않으면, 기본 포트를 선택합니"
"API 서버 사용할 포트를 선택해주세요. 선택되지 않으면, 기본 포트를 선택합니"
"다."
#: ReactNativeClient/lib/models/Setting.js:705
msgid "Enable note history"
msgstr "노트 기록 활성화"
msgstr "노트 변경 이력 활성화"
#: ReactNativeClient/lib/models/Setting.js:715
msgid "days"
@@ -2734,7 +2741,7 @@ msgstr "%d 일"
#: ReactNativeClient/lib/models/Setting.js:717
msgid "Keep note history for"
msgstr "다음과 같이 노트 기록을 유지"
msgstr "다음과 같이 노트 변경 이력을 유지"
#: ReactNativeClient/lib/models/Setting.js:744
msgid "Notebook list growth factor"
@@ -2749,6 +2756,10 @@ msgid ""
"item with a factor of 2 will take twice as much space as an item with a "
"factor of 1.Restart app to see changes."
msgstr ""
"이 인수는 각 항목들이 컨테이너 상에서 가용 공간에 적합하게 증가 혹은 감소되"
"는 방식을 설정합니다. 따라서 인수가 2인 항목은 인수가 1인 항목보다 약 2배 더 "
"많은 공간을 차지하게 될 것입니다. 변경은 애플리케이션을 재시작한 후에 적용됩"
"니다."
#: ReactNativeClient/lib/models/Setting.js:757
msgid "Note list growth factor"
@@ -2809,6 +2820,12 @@ msgid ""
"formatting. It is indicated below which plugins are compatible or not with "
"the WYSIWYG editor."
msgstr ""
"이 플러그인들은 마크다운 렌더러에 부가적인 기능들을 추가합니다. 일부 기능들"
"은 표준 마크다운에서 지원하지 않기 때문에 Jpolin에서만 동작할 수도 있음을 참"
"고하세요. 추가로, 일부 기능들은 위지윅 편집기에 *호환되지 않습니다*. 편집기에"
"서 이 플러그인을 사용하는 노트를 열게 된다면, 플러그인의 편집 내용이 유실될 "
"수도 있습니다. 아래에 어떤 플러그인들이 위지윅 편집기와의 호환되는지 표시됩니"
"다."
#: ReactNativeClient/lib/models/Setting.js:1265
#, javascript-format
@@ -2880,7 +2897,7 @@ msgstr "암호화된 항목은 변경될 수 없습니다"
#: ReactNativeClient/lib/SyncTargetOneDriveDev.js:15
msgid "OneDrive Dev (For testing only)"
msgstr "OneDrive Dev (실험용)"
msgstr "OneDrive Dev (실험용)"
#: ReactNativeClient/lib/BaseApplication.js:142
#: ReactNativeClient/lib/BaseApplication.js:155
@@ -2933,7 +2950,7 @@ msgstr "노트북으로 옮기기..."
#: ReactNativeClient/lib/components/screen-header.js:433
#, javascript-format
msgid "Move %d notes to notebook \"%s\"?"
msgstr "%d 노트를 \"%s\" 노트북으로 옮길까요?"
msgstr "%d개의 노트를 \"%s\" 노트북으로 옮길까요?"
#: ReactNativeClient/lib/components/screen-header.js:451
msgid "Press to set the decryption password."
@@ -2941,11 +2958,11 @@ msgstr "복호화 암호를 설정하려면 누르세요."
#: ReactNativeClient/lib/components/screen-header.js:452
msgid "Some items cannot be synchronised. Press for more info."
msgstr "일부 항목들 동기화할 수 없습니다. 자세한 정보를 보려면 누르세요."
msgstr "일부 항목들 동기화할 수 없습니다. 자세한 정보를 보려면 누르세요."
#: ReactNativeClient/lib/components/screen-header.js:453
msgid "The sync target needs to be upgraded. Press this banner to proceed."
msgstr ""
msgstr "동기화 대상의 업그레이드가 필요합니다. 처리를 위해 이 배너를 누르세요."
#: ReactNativeClient/lib/components/side-menu-content.js:126
#, javascript-format
@@ -2991,7 +3008,7 @@ msgid ""
"the sync target is accessible. The reported error was:"
msgstr ""
"오류. URL을 확인하시거나, 혹은 사용자명이나 비밀번호를 확인해주세요, 또한 목"
"표하는 동기화 장소가 접근가능한지 확인해주세요. 보고된 오류는 다음과 같습니"
"표하는 동기화 장소가 접근 가능한지 확인해주세요. 보고된 오류는 다음과 같습니"
"다:"
#: ReactNativeClient/lib/components/shared/dropbox-login-shared.js:39
@@ -3068,7 +3085,7 @@ msgstr "새로고침"
#: ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js:42
msgid "Sync Target Upgrade"
msgstr ""
msgstr "동기화 대상 업그레이드"
#: ReactNativeClient/lib/components/screens/NoteTagsDialog.js:163
msgid "New tags:"
@@ -3117,10 +3134,10 @@ msgid ""
"password as, for security purposes, this will be the *only* way to decrypt "
"the data! To enable encryption, please enter your password below."
msgstr ""
"암호화를 사용하게 되면 모든 노트와 첨부 파일이 다시 동기화되며, 암호화 된 상"
"로 동기화 대상에게 전달됩니다. 비밀번호는 데이터를 복구할수 있는 유일한 수"
"으로, *절대로* 비밀번호를 잃어버리지 마세요. 암호화를 사용하려면 아래에 "
"비밀번호를 넣어주세요."
"암호화를 사용하게 되면 모든 노트와 첨부 파일이 다시 동기화되며, 암호화된 상"
"로 동기화 대상에게 전달됩니다. 비밀번호는 데이터를 복구할 수 있는 유일한 수"
"으로, *절대로* 비밀번호를 잃어버리지 마세요. 암호화를 사용하려면 아래에 비밀"
"번호를 넣어주세요."
#: ReactNativeClient/lib/components/screens/encryption-config.js:177
msgid "Enable"
@@ -3181,8 +3198,7 @@ msgstr "경고"
msgid ""
"In order to use file system synchronisation your permission to write to "
"external storage is required."
msgstr ""
"파일 시스템 동기화를 사용하실려면 외부 저장소 쓰기 권한을 필요로 합니다."
msgstr "파일 시스템 동기화는 외부 저장소 쓰기 권한을 필요로 합니다."
#: ReactNativeClient/lib/components/screens/config.js:436
msgid "Tools"
@@ -3213,7 +3229,7 @@ msgid ""
"Use this to rebuild the search index if there is a problem with search. It "
"may take a long time depending on the number of notes."
msgstr ""
"검색에 오류가 있는 경우, 이를 이용하여 검색 인덱스를 다시 만들수 있습니다. 이"
"검색에 오류가 있는 경우, 이를 이용하여 검색 색인을 다시 만들 수 있습니다. 이"
"는 노트의 수에 따라 시간이 오래 걸릴수 있습니다."
#: ReactNativeClient/lib/components/screens/config.js:446
@@ -3299,7 +3315,7 @@ msgstr "Joplin 모바일 앱에서는 현재 해당 형식의 링크를 지원
#: ReactNativeClient/lib/components/screens/note.js:187
#, javascript-format
msgid "Links with protocol \"%s\" are not supported"
msgstr "링크를 위한 프로토콜 \\“%s\\”는 지원하지 않습니다"
msgstr "링크를 위한 프로토콜 “%s”는 지원하지 않습니다"
#: ReactNativeClient/lib/components/screens/note.js:617
#, javascript-format
@@ -3494,7 +3510,7 @@ msgstr "프로파일 버전: %s"
#: ReactNativeClient/lib/versionInfo.js:23
#, javascript-format
msgid "Keychain Supported: %s"
msgstr ""
msgstr "키체인 지원: %s"
#: ReactNativeClient/lib/services/InteropService_Exporter_Jex.js:29
msgid "There is no data to export."
@@ -3511,32 +3527,32 @@ msgstr "노트를 가져와서 저장할 노트북을 지정해주세요."
#: ReactNativeClient/lib/services/KeymapService.js:124
#, javascript-format
msgid "Error loading the keymap from file: %s"
msgstr ""
msgstr "파일로부터 키맵을 불러오는 중에 오류가 발생했습니다: %s"
#: ReactNativeClient/lib/services/KeymapService.js:141
#, javascript-format
msgid "Error saving the keymap to file: %s"
msgstr ""
msgstr "파일에 키맵을 저장하는 중에 오류가 발생했습니다: %s"
#: ReactNativeClient/lib/services/KeymapService.js:204
#, javascript-format
msgid "Keymap item %s is missing the required \"command\" property."
msgstr ""
msgstr "키맵 항목 %s에 필수 속성인 \"명령\"이 없습니다."
#: ReactNativeClient/lib/services/KeymapService.js:207
#, javascript-format
msgid "Keymap item %s is invalid because %s is not a valid command."
msgstr ""
msgstr "키맵 항목 %s에 유효하지 않은 명령인 %s가 지정되었습니다."
#: ReactNativeClient/lib/services/KeymapService.js:210
#, javascript-format
msgid "Keymap item %s is missing the required \"accelerator\" property."
msgstr ""
msgstr "키맵 항목 %s에 필수 속성인 \"단축키\"가 없습니다."
#: ReactNativeClient/lib/services/KeymapService.js:217
#, javascript-format
msgid "Keymap item %s is invalid because %s is not a valid accelerator."
msgstr ""
msgstr "키맵 항목 %s에 유효하지 않은 단축키인 %s가 지정되었습니다."
#: ReactNativeClient/lib/services/KeymapService.js:235
#, javascript-format
@@ -3544,11 +3560,13 @@ msgid ""
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to "
"unexpected behaviour."
msgstr ""
"단축키 \"%s\"는 \"%s\"와 \"%s\" 명령으로 사용 중입니다. 이러한 설정은 예기치 "
"못한 동작을 할 수도 있습니다."
#: ReactNativeClient/lib/services/KeymapService.js:260
#, javascript-format
msgid "Accelerator \"%s\" is not valid."
msgstr ""
msgstr "단축키 \"%s\"는 유효하지 않습니다."
#: ReactNativeClient/lib/services/report.js:121
msgid "Items that cannot be synchronised"

View File

@@ -13,9 +13,11 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.4\n"
"X-Generator: Poedit 2.4.1\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 "
"|| n%100>14) ? 1 : 2);\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
#: CliClient/app/command-cp.js:13
msgid ""
@@ -319,7 +321,7 @@ msgstr ""
#: CliClient/app/command-sync.js:35
msgid "Upgrade the sync target to the latest version."
msgstr ""
msgstr "Aktualizuj cel synchronizacji do najnowszej wersji."
#: CliClient/app/command-sync.js:81 CliClient/app/command-sync.js:95
#: ElectronClient/gui/OneDriveLoginScreen.min.js:40
@@ -818,6 +820,7 @@ msgstr "Anuluj"
msgid ""
"The app is now going to close. Please relaunch it to complete the process."
msgstr ""
"Aplikacja zostanie teraz zamknięta. Uruchom ją ponownie aby ukończyć proces."
#: ElectronClient/plugins/GotoAnything.min.js:446
msgid ""
@@ -1179,13 +1182,13 @@ msgstr "Tworzenie nowego %s..."
#: ElectronClient/gui/NoteEditor/NoteEditor.js:344
msgid "The following attachments are being watched for changes:"
msgstr ""
msgstr "Następujące załączniki są obserwowane pod kątem zmian:"
#: ElectronClient/gui/NoteEditor/NoteEditor.js:347
msgid ""
"The attachments will no longer be watched when you switch to a different "
"note."
msgstr ""
msgstr "Załączniki nie będą obserwowane gdy przejdziesz do innej notatki."
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:25
msgid "Select all"
@@ -1296,7 +1299,7 @@ msgstr "Właściwośći notatki"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:62
msgid "An unexpected error occured while importing the keymap!"
msgstr ""
msgstr "Wystąpił nieznany błąd podczas importu mapy klawiszy!"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:119
#: ElectronClient/gui/MainScreen/MainScreen.min.js:437
@@ -1311,12 +1314,11 @@ msgstr "Zaimportuj"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:125
msgid "Command"
msgstr ""
msgstr "Komenda"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:126
#, fuzzy
msgid "Keyboard Shortcut"
msgstr "Tryb klawiatury"
msgstr "Skrót klawiszowy"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:14
#: ElectronClient/app.js:690
@@ -1339,9 +1341,8 @@ msgid "Website and documentation"
msgstr "Strona internetowa i dokumentacja"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:24
#, fuzzy
msgid "Hide Joplin"
msgstr "O aplikacji Joplin"
msgstr "Ukryj okno aplikacji"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:26
#: ElectronClient/app.js:703
@@ -1349,9 +1350,8 @@ msgid "Close Window"
msgstr "Zamknij okno"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:28
#, fuzzy
msgid "Preferences"
msgstr "Preferencje..."
msgstr "Ustawienia"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:28
#: ElectronClient/gui/Root.min.js:92 ElectronClient/app.js:572
@@ -1360,13 +1360,15 @@ msgstr "Opcje"
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:48
msgid "Press the shortcut"
msgstr ""
msgstr "Naciśnij skrót klawiszowy"
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:48
msgid ""
"Press the shortcut and then press ENTER. Or, press BACKSPACE to clear the "
"shortcut."
msgstr ""
"Naciśnij skrót klawiszowy, a następnie ENTER aby potwierdzić. Naciśnij "
"BACKSPACE aby wyczyścić skrót."
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:49
#: ElectronClient/gui/EncryptionConfigScreen.min.js:95
@@ -1380,11 +1382,13 @@ msgid ""
"may take a few minutes to complete and the app needs to be restarted. To "
"proceed please click on the link."
msgstr ""
"Cel synchronizacji wymaga aktualizacji zanim Joplin może się "
"zsynchronizować. Ta operacja może zająć kilka minut po czym aplikacja będzie "
"wymagać ponownego uruchomienia. Kliknij w link aby kontynuować."
#: ElectronClient/gui/MainScreen/MainScreen.min.js:306
#, fuzzy
msgid "Restart and upgrade"
msgstr "Klucze główne do aktualizacji"
msgstr "Uruchom ponownie i aktualizuj"
#: ElectronClient/gui/MainScreen/MainScreen.min.js:313
msgid "Some items cannot be synchronised."
@@ -1825,7 +1829,7 @@ msgstr ""
"metodą."
#: ElectronClient/gui/EncryptionConfigScreen.min.js:185
#, fuzzy, javascript-format
#, javascript-format
msgid ""
"In order to do so, your entire data set will have to be encrypted and "
"synchronised, so it is best to run it overnight.\n"
@@ -2144,9 +2148,8 @@ msgid "Templates"
msgstr "Szablony"
#: ElectronClient/app.js:668
#, fuzzy
msgid "Export all"
msgstr "Eksportuj"
msgstr "Eksportuj wszystko"
#: ElectronClient/app.js:683
#, javascript-format
@@ -2178,13 +2181,12 @@ msgid "Zoom Out"
msgstr "Pomniejsz"
#: ElectronClient/app.js:852
#, fuzzy
msgid "&Note"
msgstr "Notatka"
msgstr "&Notatka"
#: ElectronClient/app.js:861
msgid "&Tools"
msgstr "&Narzędzia"
msgstr "N&arzędzia"
#: ElectronClient/app.js:865
msgid "&Help"
@@ -2360,7 +2362,7 @@ msgid ""
"The target to synchonise to. Each sync target may have additional parameters "
"which are named as `sync.NUM.NAME` (all documented below)."
msgstr ""
"Serwis z którym nastąpi snychronizacja. Każdy serwis może zawierać dodatkowe "
"Serwis z którym nastąpi synchronizacja. Każdy serwis może zawierać dodatkowe "
"parametry, które są nazwane jako `sync.NUM.NAME` (udokumentowane poniżej)."
#: ReactNativeClient/lib/models/Setting.js:110
@@ -2415,8 +2417,8 @@ msgid ""
msgstr ""
"W trybie \"Ręczny\", załączniki zostaną pobrane po naciśnięciu.W trybie "
"\"Automatyczny\", załączniki zostaną pobrane przy otwieraniu notatki. W "
"trybie \"Zawsze\", wszystkie załączniki zostaną pobrane bez względu "
"naotwarcie notatki."
"trybie \"Zawsze\", wszystkie załączniki zostaną pobrane bez względu na "
"otwarcie notatki."
#: ReactNativeClient/lib/models/Setting.js:234
msgid "Always"
@@ -2452,7 +2454,7 @@ msgstr "Motyw"
#: ReactNativeClient/lib/models/Setting.js:326
msgid "Automatically switch theme to match system theme"
msgstr "Automatycznie dopasyj motyw do motywu systemowego"
msgstr "Automatycznie dopasuj motyw do motywu systemowego"
#: ReactNativeClient/lib/models/Setting.js:338
msgid "Preferred light theme"
@@ -2460,7 +2462,7 @@ msgstr "Preferuj jasny motyw"
#: ReactNativeClient/lib/models/Setting.js:352
msgid "Preferred dark theme"
msgstr "Preferuj ciemny motyw"
msgstr "Preferuj ciemny motyw"
#: ReactNativeClient/lib/models/Setting.js:357
msgid "Show note counts"
@@ -2537,7 +2539,7 @@ msgstr "Aktywuj składnię typografu"
#: ReactNativeClient/lib/models/Setting.js:469
msgid "Enable math expressions"
msgstr "Atywuj wyrażenia matematyczne"
msgstr "Aktywuj wyrażenia matematyczne"
#: ReactNativeClient/lib/models/Setting.js:470
msgid "Enable Fountain syntax support"
@@ -2557,7 +2559,7 @@ msgstr "Aktywuj stopki"
#: ReactNativeClient/lib/models/Setting.js:475
msgid "Enable table of contents extension"
msgstr "Aktywuj rozszerenie dla tabeli zawartości"
msgstr "Aktywuj rozszerzenie dla tabeli zawartości"
#: ReactNativeClient/lib/models/Setting.js:476
msgid "Enable ~sub~ syntax"
@@ -2569,7 +2571,7 @@ msgstr "Aktywuj składnię ^sup^"
#: ReactNativeClient/lib/models/Setting.js:478
msgid "Enable deflist syntax"
msgstr "Aktywuj skladnię składnię deflist"
msgstr "Aktywuj składnię składnię deflist"
#: ReactNativeClient/lib/models/Setting.js:479
msgid "Enable abbreviation syntax"
@@ -2607,7 +2609,7 @@ msgstr ""
#: ReactNativeClient/lib/models/Setting.js:500
msgid "Start application minimised in the tray icon"
msgstr "Uruchom aplikację zminmalizowaną w zasobniku systemowym"
msgstr "Uruchom aplikację zminimalizowaną w zasobniku systemowym"
#: ReactNativeClient/lib/models/Setting.js:519
msgid "Editor font size"
@@ -2723,7 +2725,7 @@ msgstr "Pionowo"
#: ReactNativeClient/lib/models/Setting.js:639
msgid "Landscape"
msgstr "Poziomio"
msgstr "Poziomo"
#: ReactNativeClient/lib/models/Setting.js:650
msgid "Keyboard Mode"
@@ -2743,7 +2745,7 @@ msgstr "Vim"
#: ReactNativeClient/lib/models/Setting.js:670
msgid "Custom TLS certificates"
msgstr "Niestandardowe ceryfikaty TLS"
msgstr "Niestandardowe certyfikaty TLS"
#: ReactNativeClient/lib/models/Setting.js:671
msgid ""
@@ -2753,9 +2755,9 @@ msgid ""
"changes before clicking on \"Check synchronisation configuration\"."
msgstr ""
"Wykaz ścieżek katalogów podzielony przecinkami z których będą ładowane "
"ceryfikaty, lub ścieżka do odrębnych plików ceryfikacyjnych. Na przykład: /"
"my/cert_dir, /other/custom.pem. Jeżeli zostaną zmienione ustawienia TLS, "
"będzie wymagane zapisanie zmian przez naciśnięciem na \"Sprawdź konfigurację "
"certyfikaty, lub ścieżka do odrębnych plików certyfikatów. Na przykład: /my/"
"cert_dir, /other/custom.pem. Jeżeli zostaną zmienione ustawienia TLS, będzie "
"wymagane zapisanie zmian przez naciśnięciem na \"Sprawdź konfigurację "
"synchronizacji\"."
#: ReactNativeClient/lib/models/Setting.js:683
@@ -2862,9 +2864,8 @@ msgid "Web Clipper"
msgstr "Web clipper"
#: ReactNativeClient/lib/models/Setting.js:1259
#, fuzzy
msgid "Keyboard Shortcuts"
msgstr "Tryb klawiatury"
msgstr "Skróty klawiaturowe"
#: ReactNativeClient/lib/models/Setting.js:1264
msgid ""
@@ -2876,13 +2877,13 @@ msgid ""
"formatting. It is indicated below which plugins are compatible or not with "
"the WYSIWYG editor."
msgstr ""
"Te wtyczki usprawniają wyświtlanie Markdownu. Miej na uwadze, że mimo, że te "
"znaczniki mogą być przydatne, to nie są one częścią standardowego Markdownu "
"i z uwagi na to większość z nich będzie działała wyłącznie w Joplinie. "
"Dodatkowo, część z nich jest *niekompatybilna* z edytorem WYSIWYG. Jeśli "
"otworzysz notatkę używającą tego formatowania w tym edytorze, utracisz to "
"formatowanie. Poniżej jest widoczne które pluginy są kompatybilne z edytorem "
"WYSIWYG."
"Te wtyczki usprawniają wyświetlanie Markdownu. Miej na uwadze, że mimo, że "
"te znaczniki mogą być przydatne, to nie są one częścią standardowego "
"Markdownu i z uwagi na to większość z nich będzie działała wyłącznie w "
"Joplinie. Dodatkowo, część z nich jest *niekompatybilna* z edytorem WYSIWYG. "
"Jeśli otworzysz notatkę używającą tego formatowania w tym edytorze, utracisz "
"to formatowanie. Poniżej jest widoczne które pluginy są kompatybilne z "
"edytorem WYSIWYG."
#: ReactNativeClient/lib/models/Setting.js:1265
#, javascript-format
@@ -2990,15 +2991,15 @@ msgstr "Potwierdź"
#: ReactNativeClient/lib/components/CameraView.js:180
msgid "Permission to use camera"
msgstr "Uprawenie do użytkowania kamery"
msgstr "Uprawienie do użytkowania kamery"
#: ReactNativeClient/lib/components/CameraView.js:181
msgid "Your permission to use your camera is required."
msgstr "Wymagane uprawenienie do użytkowania kamery."
msgstr "Wymagane uprawnienie do użytkowania kamery."
#: ReactNativeClient/lib/components/screen-header.js:185
msgid "Delete these notes?"
msgstr "Usunąć notatki?"
msgstr "Usunąć te notatki?"
#: ReactNativeClient/lib/components/screen-header.js:392
msgid "Move to notebook..."
@@ -3007,7 +3008,7 @@ msgstr "Przenieś do notatnika..."
#: ReactNativeClient/lib/components/screen-header.js:433
#, javascript-format
msgid "Move %d notes to notebook \"%s\"?"
msgstr "Przenieś %d notatek do notatnika \"%s\"?"
msgstr "Przenieść %d notatek do notatnika \"%s\"?"
#: ReactNativeClient/lib/components/screen-header.js:451
msgid "Press to set the decryption password."
@@ -3020,6 +3021,7 @@ msgstr "Niektóre przedmioty nie mogą być zsynchronizowane."
#: ReactNativeClient/lib/components/screen-header.js:453
msgid "The sync target needs to be upgraded. Press this banner to proceed."
msgstr ""
"Cel aktualizacji wymaga aktualizacji. Kliknij w ten baner aby kontynuować."
#: ReactNativeClient/lib/components/side-menu-content.js:126
#, javascript-format
@@ -3142,7 +3144,7 @@ msgstr "Odśwież"
#: ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js:42
msgid "Sync Target Upgrade"
msgstr ""
msgstr "Aktualizacja celu synchronizacji"
#: ReactNativeClient/lib/components/screens/NoteTagsDialog.js:163
msgid "New tags:"
@@ -3193,7 +3195,7 @@ msgid ""
"the data! To enable encryption, please enter your password below."
msgstr ""
"Aktywowanie szyfrowania oznacza, że *wszystkie* Twoje notatki i załączniki "
"będą resynchronizowane i wysłane zaszyfrowane do serwisu synchonizacji. Nie "
"będą re-synchronizowane i wysłane zaszyfrowane do celu synchronizacji. Nie "
"utrać hasła, jako że, w celu zapewnienia bezpieczeństwa, będzie to *jedyna* "
"droga do deszyfrowania danych! Aby aktywować szyfrowanie, wprowadź hasło "
"poniżej."
@@ -3214,11 +3216,11 @@ msgid ""
msgstr ""
"Klucze główne z tymi ID zostaną użyte do szyfrowania niektórych obiektów, "
"jednakże aplikacja aktualnie nie ma do nich dostępu. Prawdopodobnie zostaną "
"pobrane przy synchonizacji."
"pobrane przy synchronizacji."
#: ReactNativeClient/lib/components/screens/encryption-config.js:258
msgid "Disable encryption"
msgstr "Deaktywuj szyfrowanie"
msgstr "Dezaktywuj szyfrowanie"
#: ReactNativeClient/lib/components/screens/encryption-config.js:258
msgid "Enable encryption"
@@ -3467,7 +3469,7 @@ msgstr "Utworzono lokalne obiekty: %d."
#: ReactNativeClient/lib/synchronizer.js:105
#, javascript-format
msgid "Updated local items: %d."
msgstr "Zaaktualizowano lokalne obiekty: %d."
msgstr "Zaktualizowano lokalne obiekty: %d."
#: ReactNativeClient/lib/synchronizer.js:106
#, javascript-format
@@ -3477,7 +3479,7 @@ msgstr "Utworzono zdalne obiekty: %d."
#: ReactNativeClient/lib/synchronizer.js:107
#, javascript-format
msgid "Updated remote items: %d."
msgstr "Zaaktualizowano zdalne obiekty: %d."
msgstr "Zaktualizowano zdalne obiekty: %d."
#: ReactNativeClient/lib/synchronizer.js:108
#, javascript-format
@@ -3577,7 +3579,7 @@ msgstr "Wersja profilu: %s"
#: ReactNativeClient/lib/versionInfo.js:23
#, javascript-format
msgid "Keychain Supported: %s"
msgstr ""
msgstr "Wspierany menadżer kluczy: %s"
#: ReactNativeClient/lib/services/InteropService_Exporter_Jex.js:29
msgid "There is no data to export."
@@ -3594,32 +3596,38 @@ msgstr "Proszę określić notatnik do którego będą zaimportowane notatki."
#: ReactNativeClient/lib/services/KeymapService.js:124
#, javascript-format
msgid "Error loading the keymap from file: %s"
msgstr ""
msgstr "Błąd podczas ładowania mapy klawiszy z pliku: %s"
#: ReactNativeClient/lib/services/KeymapService.js:141
#, javascript-format
msgid "Error saving the keymap to file: %s"
msgstr ""
msgstr "Błąd podczas zapisu mapy klawiszy do pliku: %s"
#: ReactNativeClient/lib/services/KeymapService.js:204
#, javascript-format
msgid "Keymap item %s is missing the required \"command\" property."
msgstr ""
"Element skrótu klawiszowego %s nie zawiera wymaganego pola: \"command\"."
#: ReactNativeClient/lib/services/KeymapService.js:207
#, javascript-format
msgid "Keymap item %s is invalid because %s is not a valid command."
msgstr ""
"Element skrótu klawiszowego %s jest niepoprawny ponieważ %s nie jest "
"prawidłową komendą."
#: ReactNativeClient/lib/services/KeymapService.js:210
#, javascript-format
msgid "Keymap item %s is missing the required \"accelerator\" property."
msgstr ""
"Element skrótu klawiszowego %s nie zawiera wymaganego pola: \"accelerator\"."
#: ReactNativeClient/lib/services/KeymapService.js:217
#, javascript-format
msgid "Keymap item %s is invalid because %s is not a valid accelerator."
msgstr ""
"Element skrótu klawiszowego %s jest niepoprawny ponieważ %s nie jest "
"prawidłową kombinacją klawiszy."
#: ReactNativeClient/lib/services/KeymapService.js:235
#, javascript-format
@@ -3627,11 +3635,13 @@ msgid ""
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to "
"unexpected behaviour."
msgstr ""
"Skrót klawiszowy \"%s\" jest już używany w komendach \"%s\" i \"%s\". Może "
"to powodować nieoczekiwane zachowanie."
#: ReactNativeClient/lib/services/KeymapService.js:260
#, javascript-format
msgid "Accelerator \"%s\" is not valid."
msgstr ""
msgstr "Skrót klawiszowy \"%s\" nie jest prawidłowy."
#: ReactNativeClient/lib/services/report.js:121
msgid "Items that cannot be synchronised"

View File

@@ -14,7 +14,9 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3.1\n"
"X-Generator: Poedit 2.4.1\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
#: CliClient/app/command-cp.js:13
msgid ""
@@ -319,7 +321,7 @@ msgstr ""
#: CliClient/app/command-sync.js:35
msgid "Upgrade the sync target to the latest version."
msgstr ""
msgstr "Senkronizasyon hedefini en son sürüme yükseltin"
#: CliClient/app/command-sync.js:81 CliClient/app/command-sync.js:95
#: ElectronClient/gui/OneDriveLoginScreen.min.js:40
@@ -813,6 +815,8 @@ msgstr "İptal et"
msgid ""
"The app is now going to close. Please relaunch it to complete the process."
msgstr ""
"Uygulama şimdi kapanacak. İşlemi tamamlamak için lütfen uygulamayı "
"kapandıktan sonar yeniden çalıştırın."
#: ElectronClient/plugins/GotoAnything.min.js:446
msgid ""
@@ -1173,13 +1177,13 @@ msgstr "Yeni %s oluşturuluyor..."
#: ElectronClient/gui/NoteEditor/NoteEditor.js:344
msgid "The following attachments are being watched for changes:"
msgstr ""
msgstr "Şu ek dosyaları değişiklikler için izlenmekte:"
#: ElectronClient/gui/NoteEditor/NoteEditor.js:347
msgid ""
"The attachments will no longer be watched when you switch to a different "
"note."
msgstr ""
msgstr "Eğer başka bir not'a geçerseniz ek dosyalar artık izlenmeyecek."
#: ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js:25
msgid "Select all"
@@ -1290,7 +1294,7 @@ msgstr "Not özellikleri"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:62
msgid "An unexpected error occured while importing the keymap!"
msgstr ""
msgstr "Tuş dizimini içe aktarırken bir hata oluştu!"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:119
#: ElectronClient/gui/MainScreen/MainScreen.min.js:437
@@ -1305,12 +1309,11 @@ msgstr "İçe aktar"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:125
msgid "Command"
msgstr ""
msgstr "Komut"
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:126
#, fuzzy
msgid "Keyboard Shortcut"
msgstr "Klavye modu"
msgstr "Klavye Kısayolu"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:14
#: ElectronClient/app.js:690
@@ -1333,9 +1336,8 @@ msgid "Website and documentation"
msgstr "Web sitesi ve dökümanlar"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:24
#, fuzzy
msgid "Hide Joplin"
msgstr "Joplin hakkında"
msgstr "Joplin'i Gizle"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:26
#: ElectronClient/app.js:703
@@ -1343,9 +1345,8 @@ msgid "Close Window"
msgstr "Pencereyi Kapat"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:28
#, fuzzy
msgid "Preferences"
msgstr "Tercihler..."
msgstr "Tercihler"
#: ElectronClient/gui/KeymapConfig/utils/getLabel.js:28
#: ElectronClient/gui/Root.min.js:92 ElectronClient/app.js:572
@@ -1354,13 +1355,15 @@ msgstr "Seçenekler"
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:48
msgid "Press the shortcut"
msgstr ""
msgstr "Kısayolu girin"
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:48
msgid ""
"Press the shortcut and then press ENTER. Or, press BACKSPACE to clear the "
"shortcut."
msgstr ""
"Kısayolu girin ve ardından ENTER tuşuna basın. Veya BACKSPACE tuşuna basarak "
"kısayolu temizleyin."
#: ElectronClient/gui/KeymapConfig/ShortcutRecorder.js:49
#: ElectronClient/gui/EncryptionConfigScreen.min.js:95
@@ -1374,11 +1377,14 @@ msgid ""
"may take a few minutes to complete and the app needs to be restarted. To "
"proceed please click on the link."
msgstr ""
"Senkronizasyon hedefi'nin Joplin senkronizasyona yeniden başlamadan once "
"güncellenmesi gerekir. Bu işlem notlarınızıın yoğunluğuna göre birkaç dakika "
"sürebilir, ve de bu işlem ardından uygulama yeniden başlatılacaktır. Bu "
"işlemi başlatmak için lütfen linke tıklayın."
#: ElectronClient/gui/MainScreen/MainScreen.min.js:306
#, fuzzy
msgid "Restart and upgrade"
msgstr "Ana anahtarların güncellenmesi lazım"
msgstr "Yeniden başlat ve güncelle"
#: ElectronClient/gui/MainScreen/MainScreen.min.js:313
msgid "Some items cannot be synchronised."
@@ -2138,9 +2144,8 @@ msgid "Templates"
msgstr "Şablonlar"
#: ElectronClient/app.js:668
#, fuzzy
msgid "Export all"
msgstr "Dışa aktar"
msgstr "Tümünü dışa aktar"
#: ElectronClient/app.js:683
#, javascript-format
@@ -2241,7 +2246,7 @@ msgstr "Bilinmeyen ID seviyesi: %s"
#: ReactNativeClient/lib/SyncTargetAmazonS3.js:28
msgid "AWS S3"
msgstr ""
msgstr "AWS S3"
#: ReactNativeClient/lib/SyncTargetDropbox.js:25
msgid "Dropbox"
@@ -2384,15 +2389,15 @@ msgstr "WebDAV şifresi"
#: ReactNativeClient/lib/models/Setting.js:195
msgid "AWS S3 bucket"
msgstr ""
msgstr "AWS S3 deposu"
#: ReactNativeClient/lib/models/Setting.js:206
msgid "AWS key"
msgstr ""
msgstr "AWS anahtarı"
#: ReactNativeClient/lib/models/Setting.js:216
msgid "AWS secret"
msgstr ""
msgstr "AWS gizli anahtarı"
#: ReactNativeClient/lib/models/Setting.js:230
msgid "Attachment download behaviour"
@@ -2850,9 +2855,8 @@ msgid "Web Clipper"
msgstr "Web Alıntılayıcısı"
#: ReactNativeClient/lib/models/Setting.js:1259
#, fuzzy
msgid "Keyboard Shortcuts"
msgstr "Klavye modu"
msgstr "Klavye Kısayolları"
#: ReactNativeClient/lib/models/Setting.js:1264
msgid ""
@@ -3008,6 +3012,8 @@ msgstr "Bazı öğeler senkronize edilemiyor. Detayları için tıklayın."
#: ReactNativeClient/lib/components/screen-header.js:453
msgid "The sync target needs to be upgraded. Press this banner to proceed."
msgstr ""
"Senkronizasyon hedefinin güncellenmesi gerekmekte. Bu banner'a tıklayarak "
"devam edebilirsiniz."
#: ReactNativeClient/lib/components/side-menu-content.js:126
#, javascript-format
@@ -3129,7 +3135,7 @@ msgstr "Yenile"
#: ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js:42
msgid "Sync Target Upgrade"
msgstr ""
msgstr "Senkronizasyon Hedefi Güncellemesi"
#: ReactNativeClient/lib/components/screens/NoteTagsDialog.js:163
msgid "New tags:"
@@ -3578,32 +3584,37 @@ msgstr "Lütfen notların alınacağı not defterini belirtin."
#: ReactNativeClient/lib/services/KeymapService.js:124
#, javascript-format
msgid "Error loading the keymap from file: %s"
msgstr ""
msgstr "%s dosyasından tuş haritası yüklenemedi"
#: ReactNativeClient/lib/services/KeymapService.js:141
#, javascript-format
msgid "Error saving the keymap to file: %s"
msgstr ""
msgstr "%s dosyasına tuş haritası kaydedilemedi"
#: ReactNativeClient/lib/services/KeymapService.js:204
#, javascript-format
msgid "Keymap item %s is missing the required \"command\" property."
msgstr ""
"%s tuş haritası, işlemler için gerekli olan \"command\" özelliğini "
"barındırmıyor."
#: ReactNativeClient/lib/services/KeymapService.js:207
#, javascript-format
msgid "Keymap item %s is invalid because %s is not a valid command."
msgstr ""
msgstr "%s tuş haritası geçersizdir, çünkü %s geçerli bir komut değildir."
#: ReactNativeClient/lib/services/KeymapService.js:210
#, javascript-format
msgid "Keymap item %s is missing the required \"accelerator\" property."
msgstr ""
"%s tuş haritası, işlemler için gerekli olan \"accelerator\" özelliğini "
"barındırmıyor."
#: ReactNativeClient/lib/services/KeymapService.js:217
#, javascript-format
msgid "Keymap item %s is invalid because %s is not a valid accelerator."
msgstr ""
"%s tuş haritası geçersizdir, çünkü %s geçerli bir accelerator değildir."
#: ReactNativeClient/lib/services/KeymapService.js:235
#, javascript-format
@@ -3611,11 +3622,13 @@ msgid ""
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to "
"unexpected behaviour."
msgstr ""
"Kısayol \"%s\", \"%s\" ve \"%s\" komutları için kullanılıyor. Bu beklenmeyen "
"sonuçlara sebep verebilir."
#: ReactNativeClient/lib/services/KeymapService.js:260
#, javascript-format
msgid "Accelerator \"%s\" is not valid."
msgstr ""
msgstr "Kısayol \"%s\" geçersiz."
#: ReactNativeClient/lib/services/report.js:121
msgid "Items that cannot be synchronised"
@@ -3949,7 +3962,7 @@ msgstr ""
#~ "Şu anda not defteriniz yok. (+) butonuna tıklayarak bir tane oluşturun."
#~ msgid "Welcome"
#~ msgstr "Hoşgeldiniz"
#~ msgstr "Hoş Geldiniz"
#~ msgid "Separate each tag by a comma."
#~ msgstr "Her etiketi virgülle ayırın."

View File

@@ -1,6 +1,6 @@
{
"name": "joplin",
"version": "1.2.0",
"version": "1.3.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -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",

View File

@@ -28,7 +28,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.2.0",
"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",

View File

@@ -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) => {

View File

@@ -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) => {

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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);

View 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);
}));
});

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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');

View File

@@ -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);

View File

@@ -3,7 +3,7 @@
require('app-module-path').addPath(__dirname);
const { asyncTest } = require('test-utils.js');
const markdownUtils = require('lib/markdownUtils.js');
const markdownUtils = require('lib/markdownUtils').default;
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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) => {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}));
});

View 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');
}));
});

View File

@@ -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);

View File

@@ -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;

View 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');
}));
});

View 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');
}));
});

View File

@@ -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');
// }));
});

View File

@@ -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);
}));
});

View File

@@ -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');

View File

@@ -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 = [

View File

@@ -0,0 +1,81 @@
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');
}));
});

View File

@@ -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) => {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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');

View File

@@ -1,163 +1,162 @@
/* eslint-disable no-unused-vars */
/* eslint prefer-const: 0*/
require('app-module-path').addPath(__dirname);
// require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest, db, synchronizer, fileApi, sleep, createNTestNotes, switchClient, createNTestFolders } = require('test-utils.js');
const SearchEngine = require('lib/services/searchengine/SearchEngine');
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 Resource = require('lib/models/Resource.js');
const { shim } = require('lib/shim');
const ResourceService = require('lib/services/ResourceService.js');
// const { time } = require('lib/time-utils.js');
// const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest, db, synchronizer, fileApi, sleep, createNTestNotes, switchClient, createNTestFolders } = require('test-utils.js');
// const SearchEngine = require('lib/services/searchengine/SearchEngine');
// 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 Resource = require('lib/models/Resource.js');
// 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);
// });
// let engine = null;
// const ids = (array) => array.map(a => a.id);
// describe('services_SearchFuzzy', function() {
// beforeEach(async (done) => {
// await setupDatabaseAndSynchronizer(1);
// await switchClient(1);
// engine = new SearchEngine();
// engine.setDb(db());
// Setting.setValue('db.fuzzySearchEnabled', 1);
// done();
// });
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
// it('should return note almost matching title', asyncTest(async () => {
// let rows;
// const n1 = await Note.save({ title: 'If It Ain\'t Baroque, Don\'t Fix It' });
// const n2 = await Note.save({ title: 'Important note' });
let engine = null;
// await engine.syncTables();
// rows = await engine.search('Broke', { fuzzy: false });
// expect(rows.length).toBe(0);
const ids = (array) => array.map(a => a.id);
describe('services_SearchFuzzy', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
engine = new SearchEngine();
engine.setDb(db());
Setting.setValue('db.fuzzySearchEnabled', 1);
done();
});
// rows = await engine.search('Broke', { fuzzy: true });
// expect(rows.length).toBe(1);
// expect(rows[0].id).toBe(n1.id);
it('should return note almost matching title', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'If It Ain\'t Baroque, Don\'t Fix It' });
const n2 = await Note.save({ title: 'Important note' });
// rows = await engine.search('title:Broke', { fuzzy: true });
// expect(rows.length).toBe(1);
// expect(rows[0].id).toBe(n1.id);
await engine.syncTables();
rows = await engine.search('Broke', { fuzzy: false });
expect(rows.length).toBe(0);
// rows = await engine.search('title:"Broke"', { fuzzy: true });
// expect(rows.length).toBe(1);
// expect(rows[0].id).toBe(n1.id);
rows = await engine.search('Broke', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
// rows = await engine.search('Imprtant', { fuzzy: true });
// expect(rows.length).toBe(1);
// expect(rows[0].id).toBe(n2.id);
// }));
rows = await engine.search('title:Broke', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
// it('should order results by min fuzziness', asyncTest(async () => {
// let rows;
// const n1 = await Note.save({ title: 'I demand you take me to him' });
// const n2 = await Note.save({ title: 'He demanded an answer' });
// const n3 = await Note.save({ title: 'Don\'t you make demands of me' });
// const n4 = await Note.save({ title: 'No drama for me' });
// const n5 = await Note.save({ title: 'Just minding my own business' });
rows = await engine.search('title:"Broke"', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
rows = await engine.search('Imprtant', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n2.id);
}));
// await engine.syncTables();
// rows = await engine.search('demand', { fuzzy: false });
// expect(rows.length).toBe(1);
// expect(rows[0].id).toBe(n1.id);
it('should order results by min fuzziness', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'I demand you take me to him' });
const n2 = await Note.save({ title: 'He demanded an answer' });
const n3 = await Note.save({ title: 'Don\'t you make demands of me' });
const n4 = await Note.save({ title: 'No drama for me' });
const n5 = await Note.save({ title: 'Just minding my own business' });
// rows = await engine.search('demand', { fuzzy: true });
// expect(rows.length).toBe(3);
// expect(rows[0].id).toBe(n1.id);
// expect(rows[1].id).toBe(n3.id);
// expect(rows[2].id).toBe(n2.id);
// }));
await engine.syncTables();
rows = await engine.search('demand', { fuzzy: false });
expect(rows.length).toBe(1);
expect(rows[0].id).toBe(n1.id);
// it('should consider any:1', asyncTest(async () => {
// let rows;
// const n1 = await Note.save({ title: 'cat' });
// const n2 = await Note.save({ title: 'cats' });
// const n3 = await Note.save({ title: 'cot' });
// const n4 = await Note.save({ title: 'defenestrate' });
// const n5 = await Note.save({ title: 'defenstrate' });
// const n6 = await Note.save({ title: 'defenestrated' });
rows = await engine.search('demand', { fuzzy: true });
expect(rows.length).toBe(3);
expect(rows[0].id).toBe(n1.id);
expect(rows[1].id).toBe(n3.id);
expect(rows[2].id).toBe(n2.id);
}));
// const n7 = await Note.save({ title: 'he defenestrated the cat' });
it('should consider any:1', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'cat' });
const n2 = await Note.save({ title: 'cats' });
const n3 = await Note.save({ title: 'cot' });
// await engine.syncTables();
const n4 = await Note.save({ title: 'defenestrate' });
const n5 = await Note.save({ title: 'defenstrate' });
const n6 = await Note.save({ title: 'defenestrated' });
// rows = await engine.search('defenestrated cat', { fuzzy: true });
// expect(rows.length).toBe(1);
const n7 = await Note.save({ title: 'he defenestrated the cat' });
// rows = await engine.search('any:1 defenestrated cat', { fuzzy: true });
// expect(rows.length).toBe(7);
// }));
await engine.syncTables();
// it('should leave phrase searches alone', asyncTest(async () => {
// let rows;
// const n1 = await Note.save({ title: 'abc def' });
// const n2 = await Note.save({ title: 'def ghi' });
// const n3 = await Note.save({ title: 'ghi jkl' });
// const n4 = await Note.save({ title: 'def abc' });
// const n5 = await Note.save({ title: 'mno pqr ghi jkl' });
rows = await engine.search('defenestrated cat', { fuzzy: true });
expect(rows.length).toBe(1);
// await engine.syncTables();
rows = await engine.search('any:1 defenestrated cat', { fuzzy: true });
expect(rows.length).toBe(7);
}));
// rows = await engine.search('abc def', { fuzzy: true });
// expect(rows.length).toBe(2);
// expect(rows.map(r=>r.id)).toContain(n1.id);
// expect(rows.map(r=>r.id)).toContain(n4.id);
it('should leave phrase searches alone', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'abc def' });
const n2 = await Note.save({ title: 'def ghi' });
const n3 = await Note.save({ title: 'ghi jkl' });
const n4 = await Note.save({ title: 'def abc' });
const n5 = await Note.save({ title: 'mno pqr ghi jkl' });
// rows = await engine.search('"abc def"', { fuzzy: true });
// expect(rows.length).toBe(1);
// expect(rows.map(r=>r.id)).toContain(n1.id);
await engine.syncTables();
// rows = await engine.search('"ghi jkl"', { fuzzy: true });
// expect(rows.length).toBe(2);
// expect(rows.map(r=>r.id)).toContain(n3.id);
// expect(rows.map(r=>r.id)).toContain(n5.id);
rows = await engine.search('abc def', { fuzzy: true });
expect(rows.length).toBe(2);
expect(rows.map(r=>r.id)).toContain(n1.id);
expect(rows.map(r=>r.id)).toContain(n4.id);
// rows = await engine.search('"ghi jkl" mno', { fuzzy: true });
// expect(rows.length).toBe(1);
// expect(rows.map(r=>r.id)).toContain(n5.id);
rows = await engine.search('"abc def"', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows.map(r=>r.id)).toContain(n1.id);
// rows = await engine.search('any:1 "ghi jkl" mno', { fuzzy: true });
// expect(rows.length).toBe(2);
// expect(rows.map(r=>r.id)).toContain(n3.id);
// expect(rows.map(r=>r.id)).toContain(n5.id);
// }));
rows = await engine.search('"ghi jkl"', { fuzzy: true });
expect(rows.length).toBe(2);
expect(rows.map(r=>r.id)).toContain(n3.id);
expect(rows.map(r=>r.id)).toContain(n5.id);
// it('should leave wild card searches alone', asyncTest(async () => {
// let rows;
// const n1 = await Note.save({ title: 'abc def' });
// const n2 = await Note.save({ title: 'abcc ghi' });
// const n3 = await Note.save({ title: 'abccc ghi' });
// const n4 = await Note.save({ title: 'abcccc ghi' });
// const n5 = await Note.save({ title: 'wxy zzz' });
rows = await engine.search('"ghi jkl" mno', { fuzzy: true });
expect(rows.length).toBe(1);
expect(rows.map(r=>r.id)).toContain(n5.id);
// await engine.syncTables();
rows = await engine.search('any:1 "ghi jkl" mno', { fuzzy: true });
expect(rows.length).toBe(2);
expect(rows.map(r=>r.id)).toContain(n3.id);
expect(rows.map(r=>r.id)).toContain(n5.id);
}));
// rows = await engine.search('abc*', { fuzzy: true });
it('should leave wild card searches alone', asyncTest(async () => {
let rows;
const n1 = await Note.save({ title: 'abc def' });
const n2 = await Note.save({ title: 'abcc ghi' });
const n3 = await Note.save({ title: 'abccc ghi' });
const n4 = await Note.save({ title: 'abcccc ghi' });
const n5 = await Note.save({ title: 'wxy zzz' });
// expect(rows.length).toBe(4);
// expect(rows.map(r=>r.id)).toContain(n1.id);
// expect(rows.map(r=>r.id)).toContain(n2.id);
// expect(rows.map(r=>r.id)).toContain(n3.id);
// expect(rows.map(r=>r.id)).toContain(n4.id);
// }));
await engine.syncTables();
rows = await engine.search('abc*', { fuzzy: true });
expect(rows.length).toBe(4);
expect(rows.map(r=>r.id)).toContain(n1.id);
expect(rows.map(r=>r.id)).toContain(n2.id);
expect(rows.map(r=>r.id)).toContain(n3.id);
expect(rows.map(r=>r.id)).toContain(n4.id);
}));
});
// });

View File

@@ -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);
// }));
// });

View File

@@ -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');

View File

@@ -3,13 +3,13 @@
require('app-module-path').addPath(__dirname);
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('test-utils.js');
const Api = require('lib/services/rest/Api');
const Api = require('lib/services/rest/Api').default;
const Folder = require('lib/models/Folder');
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);

View File

@@ -2,6 +2,7 @@
"spec_dir": "tests-build",
"spec_files": [
"*.js",
"services/plugins/*.js",
"!test-utils.js"
],
"stopSpecOnExpectationFailure": false,

View File

@@ -0,0 +1 @@
_temp

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