1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-27 20:29:45 +02:00

Compare commits

...

515 Commits

Author SHA1 Message Date
Laurent Cozic
0f9da943cd Android 2.14.6 2024-02-09 12:45:52 +00:00
Laurent Cozic
485a685e5a Desktop release v2.14.13 2024-02-09 12:21:37 +00:00
Joplin Bot
3a0b180487 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-02-09 12:19:03 +00:00
Laurent Cozic
605233c572 Ignore Renovate package 2024-02-09 12:17:30 +00:00
Max Patiiuk
37344fe718 Doc: use correct package names for turndown (#9882)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-09 12:16:41 +00:00
Max Patiiuk
f74570b403 Doc: explain how to get TypeScript typings (#9883)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-09 12:16:18 +00:00
renovate[bot]
13f907e7f1 Update dependency nodemon to v3.0.3 (#9895)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:15:35 +00:00
renovate[bot]
f2ee35c82a Update dependency react-native-share to v10.0.2 (#9897)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:15:26 +00:00
renovate[bot]
29d4a026e2 Update dependency react-native-localize to v3.0.6 (#9896)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:15:21 +00:00
renovate[bot]
c7e312e959 Update dependency node-mocks-http to v1.14.1 (#9894)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:15:14 +00:00
renovate[bot]
e6a811e259 Update dependency @react-native-community/netinfo to v11.2.1 (#9898)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:14:59 +00:00
renovate[bot]
5408dd71d3 Update dependency koa to v2.15.0 (#9899)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:14:46 +00:00
renovate[bot]
edc8865e50 Update dependency moment to v2.30.1 (#9900)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-09 12:14:30 +00:00
Max Patiiuk
a80fea9c4b Chore: fix cache memory leak in turndown (#9886)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-09 12:12:45 +00:00
pedr
92c85ca07c Mobile: Fixes #9475: Increase space available for Notebook icon (#9877)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-09 12:11:51 +00:00
Henry Heino
296d586b04 Mobile,Desktop,Cli: Improve search engine error handling when preparing text for search (#9871)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-09 12:11:08 +00:00
Laurent Cozic
6f0fd4219e Desktop: Make OCR results available to search immediately after completion 2024-02-09 11:56:23 +00:00
renovate[bot]
35fe392058 Update dependency async-mutex to v0.4.1 (#9893)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-08 23:36:08 +00:00
renovate[bot]
61f8a2afd3 Update dependency @types/react to v18.2.48 (#9892)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-08 23:33:13 +00:00
Henry Heino
347ba9bb38 Mobile: Fixes #9858: Fix deeply-nested subnotebook titles invisible in the folder dropdown (#9906) 2024-02-08 23:17:17 +00:00
Henry Heino
802f6c462e Desktop: Fixes #9891: Don't rerender markdown notes when the note preview pane is hidden (#9901) 2024-02-08 22:49:29 +00:00
Henry Heino
39b44ff439 Desktop: Disable built-in copy of Simple Backup by default in Joplin Portable (#9907) 2024-02-08 22:48:39 +00:00
Henry Heino
627b830739 Desktop: Fix mermaid save button partially hidden behind graph (#9888) 2024-02-08 18:41:19 +00:00
Laurent Cozic
d58185afe0 Chore: Add more debug info when assets cannot be unloaded 2024-02-08 18:14:08 +00:00
Laurent Cozic
0b3a5a431d Desktop, Mobile, Cli: Fixes #9694: Correctly search HTML-entity encoded text 2024-02-08 18:14:07 +00:00
Henry Heino
c54603025b Chore: Desktop: Fixes #9873: Fix Playwright test failure due to image not visible (#9874) 2024-02-08 16:56:12 +00:00
Henry Heino
debd8a6ebe Chore: Remove .gitignored file from version control (#9872) 2024-02-08 16:55:48 +00:00
Henry Heino
d614d40cfd Desktop: Fixes #9868: Fix markdown (frontmatter) notes that start with a UTF-8 BOM aren't imporetd correctly (#9875) 2024-02-08 16:55:34 +00:00
Henry Heino
628877147e Mobile: Fixes #9863: Fix share to Joplin when only "All notes" has been opened (#9876)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-08 16:54:23 +00:00
pedr
c163491371 Desktop: Fixes #9763: Suppress random error that happens during desktop shutdown (#9878)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-08 16:51:32 +00:00
Laurent Cozic
16d77bfa10 Doc: Documented Sentry integration 2024-02-08 14:51:24 +00:00
Laurent Cozic
11e1a49b5c Desktop: Fixes #9607: Copied and pasted text from Firefox to RTE does not include images 2024-02-08 13:06:18 +00:00
Laurent Cozic
b1877fcd0d Desktop: Speed up pasting text and images in Rich Text Editor 2024-02-08 12:51:31 +00:00
Laurent Cozic
4b7f0bfbb9 fixed test 2024-02-08 11:57:30 +00:00
github-actions[bot]
2f06697aa2 @maxpatiiuk has signed the CLA in laurent22/joplin#9882 2024-02-08 03:53:06 +00:00
Laurent Cozic
07aba918a0 Desktop: Disable initial Sentry request when crash auto-upload is disabled 2024-02-07 18:05:13 +00:00
Henry Heino
01ec640bdb Chore: Refactor string-utils to TypeScript (#9869) 2024-02-07 14:16:54 +00:00
renovate[bot]
c1e5adf658 Update dependency @types/node to v18.19.8 (#9866)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-07 02:35:16 +00:00
Henry Heino
a364f66d4b Android: Fixes #7974: Fix regression: Crash when opening appearance/sync settings on some devices (#9864) 2024-02-06 16:27:12 +00:00
Henry Heino
a906e73b22 Desktop: PDF search text: Remove NULL characters early to avoid possible sync issues (#9862) 2024-02-06 16:24:00 +00:00
Henry Heino
8b9ce9ec72 Desktop: Fixes #9855: Allow using editor commands in the command palette (#9861) 2024-02-06 16:20:15 +00:00
Henry Heino
e462881502 MacOS: Resolves #9488: Add "Window" menu to toolbar on MacOS (#9859) 2024-02-06 16:19:52 +00:00
Laurent Cozic
0e8f0a2dc1 Update translations 2024-02-06 16:15:34 +00:00
renovate[bot]
2252a06a50 Update dependency @types/node-fetch to v2.6.11 (#9865)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-06 15:50:38 +00:00
Cristi
6ecc478402 Translated text in ro.po and rename file to ro_RO.po (#9717)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-02-06 15:49:12 +00:00
Laurent Cozic
da06383458 Doc: Add GSoC 2024 folder 2024-02-05 12:09:37 +00:00
renovate[bot]
a56c78db8b Update dependency @types/node to v18.19.7 (#9853)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 05:06:10 +00:00
Henry Heino
6ebc7993be Desktop: Fixes #9832: Fix user-installed versions of built-in plugins can't access resources in some cases (#9849) 2024-02-03 20:28:47 +01:00
renovate[bot]
b8243e5518 Update dependency react-native-share to v10 (#9848)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:28:32 +01:00
renovate[bot]
a5a4aaf765 Update dependency @react-native-community/netinfo to v11 (#9846)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:28:03 +01:00
renovate[bot]
0f793a4cf0 Update dependency react-native-safe-area-context to v4.8.2 (#9844)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:27:24 +01:00
renovate[bot]
ce11761dc9 Update dependency react-native-document-picker to v9.1.0 (#9843)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:27:10 +01:00
renovate[bot]
437b3bbfe8 Update dependency node-mocks-http to v1.14.0 (#9842)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:26:55 +01:00
renovate[bot]
6dbfa6e4d8 Update dependency @react-native-community/slider to v4.5.0 (#9840)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:26:29 +01:00
renovate[bot]
3451133fd7 Update dependency @js-draw/material-icons to v1.16.1 (#9839)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:26:16 +01:00
renovate[bot]
1932187e0f Update dependency style-loader to v3.3.4 (#9838)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:26:10 +01:00
renovate[bot]
eefde7baba Update dependency sqlite3 to v5.1.7 (#9837)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:26:04 +01:00
renovate[bot]
a225c11822 Update dependency sharp to v0.33.2 (#9836)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:25:44 +01:00
renovate[bot]
b35246cd64 Update dependency react-native-paper to v5.11.7 (#9835)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:25:37 +01:00
renovate[bot]
4289c08538 Update dependency react-native-localize to v3.0.5 (#9834)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:25:30 +01:00
renovate[bot]
b58ca5095c Update dependency follow-redirects to v1.15.5 (#9833)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:25:21 +01:00
renovate[bot]
a2e5125335 Update dependency js-draw to v1.16.1 (#9841)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-03 20:25:08 +01:00
Joplin Bot
7938eab6e2 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-02-03 12:18:52 +00:00
renovate[bot]
b322ff247c Update dependency sass to v1.69.7 (#9741)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-02 23:49:16 +00:00
Laurent Cozic
fc8fadce2b Update renovate.json5 2024-02-03 00:37:54 +01:00
Laurent Cozic
9485c323d1 iOS 12.14.3 2024-02-03 00:35:09 +01:00
renovate[bot]
40749cabff Update dependency react-native-webview to v13.6.4 (#9773)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-02 23:29:59 +00:00
renovate[bot]
cddd8213d5 Update dependency ldapts to v7.0.8 (#9790)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-02 23:26:34 +00:00
Laurent Cozic
fd48697fb2 Android 2.14.5 2024-02-03 00:12:14 +01:00
Laurent Cozic
28819931a3 Desktop release v2.14.12 2024-02-03 00:02:22 +01:00
Henry Heino
815fe8d3ba Desktop: Resolves #9765: OCR: Use existing PDF text when available (#9764) 2024-02-02 23:59:15 +01:00
Henry Heino
564adb9a57 Desktop: Fixes #9829: Fix mermaid save button creates additional space above diagrams (#9830) 2024-02-02 23:57:57 +01:00
Henry Heino
987417502f Desktop: Fixes #9826: Fix drag-and-drop of images and text in the rich text editor (#9827) 2024-02-02 23:57:26 +01:00
Henry Heino
43d36f9415 Desktop: Fixes #9822: Allow dialogs to scroll on small screens (#9823) 2024-02-02 23:57:07 +01:00
pedr
24776ee6ce Desktop: Fixes #9737: Fix ghosting when dropping code block over another code block (#9816) 2024-02-02 23:56:14 +01:00
Henry Heino
9a26e8aafd Chore: Default plugins: Refactor git checkout in default plugins build (#9812) 2024-02-02 23:55:28 +01:00
Henry Heino
0e45336140 Desktop: Fixes #9817: Fix scrollbars shown unnecessarily when opening the tag dialog (#9818) 2024-02-02 23:54:44 +01:00
Henry Heino
2d4fc08f2b Desktop: Fixes #9629: Fix horizontal touchpad scrolling of code blocks (#9815) 2024-02-02 18:50:56 +00:00
Henry Heino
b51e16c255 Chore: Desktop: Remove duplicate buildDir-finding logic (#9811) 2024-02-02 18:34:38 +00:00
Henry Heino
bc8392ad52 Linux: Fixes #8240: Fix print on Linux (#9810) 2024-02-02 18:19:01 +00:00
Joplin Bot
dba218a681 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-02-02 18:16:38 +00:00
Henry Heino
e83306c1f7 Mobile: Resolves #9819: Allow note viewer to extend to the edge of the screen while pinch zooming (#9820) 2024-02-02 18:10:27 +00:00
Henry Heino
a0f003f9d5 Desktop: Fixes #9597: Fix image rotation not preserved when resizing an attached image (#9824) 2024-02-02 17:58:27 +00:00
Henry Heino
0e6b5b338c Desktop: Fixes #9786: Rich text editor: Fix newline behavior in new notes (#9809) 2024-02-02 17:56:58 +00:00
Henry Heino
ddbd3601ab Mobile: Fixes #9807: Fix note editor errors/logs not sent to Joplin's logs (#9808) 2024-02-02 17:54:16 +00:00
Henry Heino
236d977c41 Desktop,Mobile,Cli: Fixes #9800: Fix synchronization happens every 10 seconds even if nothing has changed (#9814) 2024-02-02 17:53:22 +00:00
Henry Heino
7c539976dd Mobile: Fixes #7974: Andoid: Fix crash on opening settings on some devices (#9806) 2024-02-02 17:51:26 +00:00
Henry Heino
fa0b741529 All: Fixes #9799: Fix broken synchronisation link in welcome notes (#9804) 2024-02-02 17:50:52 +00:00
Henry Heino
a133bb06a3 Mobile: Fixes #9142: Detect faster left-right swipes to open the sidemenu (#9802) 2024-02-02 17:49:23 +00:00
Henry Heino
e71ec2bc49 Desktop: Fixes #8736: Fix images with SVG data URLs corrupted in the rich text editor (#9801) 2024-02-02 17:48:26 +00:00
Henry Heino
99e8818ba0 Chore: Desktop: Fix default-plugins build doesn't checkout the correct commit (#9813)
Fixes an issue where the default plugins build script didn't always checkout the correct commit before building.
2024-02-01 08:06:29 -08:00
renovate[bot]
e4197a985e Update dependency @types/node to v18.19.6 (#9805)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-01 08:09:45 +00:00
Joplin Bot
c023cee0b8 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-02-01 06:16:25 +00:00
Joplin Bot
e42fa68114 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-02-01 00:38:04 +00:00
github-actions[bot]
582f0853bb @tiberiusteng has signed the CLA in laurent22/joplin#9803 2024-01-30 06:52:44 +00:00
renovate[bot]
07ee20a0ff Update dependency @types/node to v18.19.5 (#9798)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-28 21:16:37 +00:00
renovate[bot]
7f78e94d6e Update dependency @types/react to v18.2.47 (#9789)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-28 18:55:10 +00:00
Henry Heino
3fbf5ef5d0 Chore: Default plugins: Rename patch to patch-plugin (#9797) 2024-01-28 18:53:13 +00:00
Laurent Cozic
25b12a2366 Desktop: Fixes #9433: Fixed various scrolling issues when creating new notes or to-dos 2024-01-28 17:57:41 +00:00
Laurent Cozic
07b4117aa1 Desktop, Mobile: Resolves #9263: Do not allow switching the sync target if not all resources are downloaded 2024-01-27 18:28:14 +00:00
Laurent Cozic
8abd9b401b Desktop, Mobile: Fixes #9157: Clear "Some items cannot be synchronised" banner after situation is resolved 2024-01-27 18:28:13 +00:00
Joplin Bot
1c5a79c353 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-27 18:14:57 +00:00
Laurent Cozic
149e409bfa Desktop, Mobile: Fixes #9157: Clear "Some items cannot be synchronised" banner after situation is resolved 2024-01-27 16:59:19 +00:00
Laurent Cozic
e4854b0bc2 Clipper: Fixed clipping Markdown 2024-01-27 15:44:18 +00:00
Laurent Cozic
857e25d84f Doc: Added news item about new plugin manifest info 2024-01-27 15:04:01 +00:00
Laurent Cozic
af59295968 Desktop: Removed obsolete template-related banner 2024-01-27 10:41:31 +00:00
Laurent Cozic
c94ec4e064 Chore: Rename instances of yarn run to just yarn 2024-01-26 20:19:28 +00:00
Laurent Cozic
999baf4b3d Desktop, Mobile, Cli: Resolves #9769: Removed ability to search by note ID to fix issue with certain plugins 2024-01-26 20:15:00 +00:00
renovate[bot]
bfb802cd09 Update dependency react-native-paper to v5.11.6 (#9772)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-26 19:48:46 +00:00
renovate[bot]
61cd924bb1 Update dependency nodemailer to v6.9.8 (#9771)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-26 19:45:39 +00:00
Laurent Cozic
3e13a95053 Desktop: Fixes #9512: Pasting rich text in the RTE sometimes result in invalid markup 2024-01-26 19:14:31 +00:00
Henry Heino
b69d752734 Chore: Desktop: Fix slow startup issue: defaultPlugins directory not cleaned on rebuild (#9785) 2024-01-26 19:11:22 +00:00
Joplin Bot
821cc346f7 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-26 18:16:35 +00:00
Laurent Cozic
8402c20a3f Desktop: Removed double Sentry initialization 2024-01-26 18:06:52 +00:00
Laurent Cozic
4c50706d54 Android 2.14.4 2024-01-26 10:59:16 +00:00
Laurent Cozic
0f9d6a12b0 Desktop release v2.14.11 2024-01-26 10:35:29 +00:00
Henry Heino
13da286b55 Desktop: Fixes #9781: Extract default plugins to directories matching their IDs (#9782) 2024-01-26 10:33:48 +00:00
Henry Heino
da4d57c1db Desktop: Fixes #9779: Linux: Fix bundled Simple Backup can't create 7zip archives (#9780) 2024-01-26 10:33:15 +00:00
Laurent Cozic
7b06090255 Desktop, Mobile, Cli: Allow setting a minimum app version on the sync target (#9778) 2024-01-26 10:32:35 +00:00
Laurent Cozic
2cc4ac087b Update publish_note.md 2024-01-26 10:12:51 +00:00
Henry Heino
c4ff7857b1 Desktop: Fixes #9775: Fix search when note or OCR text contains null characters (#9774) 2024-01-25 17:03:53 +00:00
Laurent Cozic
938e639a01 Doc: Document info.json file 2024-01-25 16:49:19 +00:00
Laurent Cozic
fe3ad3e9b4 Desktop: Write a crash dump to disk when the app crashes 2024-01-25 11:33:04 +00:00
Helmut K. C. Tessarek
681d413b36 Linux: style: make install script more consistent 2024-01-23 17:42:03 +01:00
Helmut K. C. Tessarek
8b452106be Linux: set colors conditionally in install script 2024-01-23 17:14:14 +01:00
renovate[bot]
72a8724a5b Update dependency follow-redirects to v1.15.4 (#9770)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-23 13:04:22 +00:00
renovate[bot]
04112b025c Update dependency source-map-loader to v4.0.2 (#9742)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-23 09:10:15 +00:00
github-actions[bot]
bea9edf64b @redisded has signed the CLA in laurent22/joplin#9768 2024-01-22 21:20:42 +00:00
Laurent Cozic
fd432f928d Plugins: Add support for promo_tile manifest key 2024-01-22 17:16:27 +00:00
Laurent Cozic
a8f6676fb3 Chore: Convert CLI app class to TS 2024-01-22 17:16:26 +00:00
Henry Heino
6720fd1f0e Desktop: Fixes #9752: CodeMirror 6 plugin API: Allow importing @codemirror/lang-markdown and @lezer/highlight (#9753) 2024-01-22 15:28:00 +00:00
Henry Heino
f3518cddbe Desktop: Resolves #9747: CodeMirror 6 plugin API: Support non-inline CSS assets (#9748) 2024-01-22 15:27:42 +00:00
pedr
d4d400217b API: Increase protection of files downloaded via the REST API (#9676) 2024-01-22 14:46:18 +00:00
Laurent Cozic
a863f92490 Desktop: Moved crash report auto-upload option under pre-release option 2024-01-20 11:47:02 +00:00
Laurent Cozic
aaf4dcc50c lock file 2024-01-19 19:20:10 +00:00
renovate[bot]
cfd34da03f Update dependency @types/node to v18.19.4 (#9749)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-19 10:42:50 +00:00
Joplin Bot
c24467c15e Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-19 00:39:55 +00:00
Laurent Cozic
3ed6ad5948 Desktop release v2.14.10 2024-01-18 21:57:08 +00:00
Laurent Cozic
de0ae7653f Desktop: Add support for automatically uploading crash reports 2024-01-18 21:45:25 +00:00
Laurent Cozic
a9691f6b1c Doc: Added Celebian sponsor 2024-01-18 18:39:06 +00:00
Laurent Cozic
1a7d463f09 Doc: Fixed server readme 2024-01-18 18:07:15 +00:00
Laurent Cozic
47a49fd5de Server v2.14.2 2024-01-18 17:23:51 +00:00
Laurent Cozic
be949390f8 Server: Revert to Formidable v2 to avoid random crashes
Ref: https://github.com/node-formidable/formidable/issues/958
2024-01-18 17:21:02 +00:00
renovate[bot]
b26a9f1b22 Update dependency knex to v3.1.0 (#9743)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-18 15:13:48 +00:00
renovate[bot]
b7b0f770ee Update dependency react-native-paper to v5.11.5 (#9740)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-18 14:24:15 +00:00
renovate[bot]
1ae5d4ea9b Update dependency @types/react to v18.2.46 (#9739)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-18 14:11:05 +00:00
Joplin Bot
aa267f0dc6 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-18 12:19:47 +00:00
Henry Heino
691618b50c Mobile: Hide advanced settings by default (#9730) 2024-01-18 11:26:51 +00:00
Henry Heino
33ed7545a9 Mobile: Add support for showing only lines of log that contain a filter (#9728) 2024-01-18 11:26:32 +00:00
Henry Heino
d8d0e705f2 Desktop: Fixes #9725: Fix warning logged when uninstalling multiple plugins (#9726) 2024-01-18 11:24:44 +00:00
Henry Heino
bdc970d718 Chore: Fixes #9710: Default plugins build: Fetch when checkout fails (#9711)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-01-18 11:22:39 +00:00
Henry Heino
4636d1539c Chore: Mobile: Refactor markdown toolbar (#9708) 2024-01-18 11:22:20 +00:00
Henry Heino
bc1165be46 Desktop,Mobile,Cli: Resolves #9706: Don't log OneDrive Authorization tokens (#9707) 2024-01-18 11:20:33 +00:00
Henry Heino
f5e1e45f6f Chore: Refactor renderer package: Limit dependency on @joplin/lib and improve type safety (#9701) 2024-01-18 11:20:10 +00:00
renovate[bot]
352ee6496e Update dependency @types/node-fetch to v2.6.10 (#9738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-18 11:17:19 +00:00
Henry Heino
fdbfa78e53 Desktop: Fixes #9699: Beta editor: Fix o not working in Vim normal mode (#9700) 2024-01-18 11:16:38 +00:00
Laurent Cozic
dfe5383d4b Doc: Added Celebian sponsor 2024-01-18 11:04:36 +00:00
Laurent Cozic
eb1e9e0436 Doc: Removed sponsor 2024-01-18 11:03:13 +00:00
renovate[bot]
3d7f864982 Update dependency js-draw to v1.15.0 (#9732)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-16 12:56:35 +00:00
renovate[bot]
1ffe30b359 Update dependency @js-draw/material-icons to v1.15.0 (#9731)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-16 12:56:28 +00:00
renovate[bot]
5d5bd3abd6 Update dependency lint-staged to v15.2.0 (#9733)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-16 10:39:56 +00:00
Joplin Bot
747264bd89 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-16 06:17:24 +00:00
Joplin Bot
7bd1bdb0e3 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-16 00:39:12 +00:00
Joplin Bot
d5ec92e540 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-15 18:16:36 +00:00
github-actions[bot]
2b50e99bb1 @msorens has signed the CLA in laurent22/joplin#9721 2024-01-15 01:24:49 +00:00
Laurent Cozic
a4c5164bea Chore: Fixed file checking logic on resource fetcher 2024-01-14 14:57:29 +00:00
github-actions[bot]
88d6c94e6b @idcristi has signed the CLA in laurent22/joplin#9717 2024-01-14 13:45:34 +00:00
renovate[bot]
4f45c977e2 Update dependency @types/node to v18.19.3 (#9716)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-14 12:38:58 +00:00
Laurent Cozic
cbf7e24c47 Desktop, Cli, Mobile: Display an error if a resource cannot be downloaded 2024-01-14 12:35:20 +00:00
Laurent Cozic
7ebc98633a Desktop: Fixes existing attachments not being shared in some cases with Joplin Server 2024-01-14 12:33:40 +00:00
Laurent Cozic
1d4e3fe3ea Chore: Renovate: automerge types 2024-01-14 09:58:05 +00:00
renovate[bot]
94e0ea403a Update dependency react-native-image-picker to v7.1.0 (#9713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-14 09:57:34 +00:00
renovate[bot]
d217478852 Update dependency lint-staged to v15 (#9714)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-14 09:57:26 +00:00
renovate[bot]
4c9cbd61a4 Update dependency @types/node to v18.19.2 (#9712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-14 09:57:06 +00:00
Joplin Bot
d07a540618 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-14 00:43:47 +00:00
Laurent Cozic
720b6f0190 Server: Resolves #9695: Check Postgres required version before starting the server 2024-01-13 19:34:14 +00:00
renovate[bot]
33fff4c8f0 Update react monorepo (#9665)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-13 19:20:27 +00:00
Laurent Cozic
6f83ccd044 Chore: Try to fix random test timeout 2024-01-13 19:10:34 +00:00
Laurent Cozic
7d68dafaed Chore: Change postinstall script to a build script 2024-01-13 19:06:40 +00:00
Laurent Cozic
4f066b06d2 Desktop: Fixes #9709: Shared notebook can get corrupted if contributor changes its title 2024-01-13 18:17:47 +00:00
Joplin Bot
a11bed1bb2 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-13 00:38:37 +00:00
Joplin Bot
96c9e29025 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-12 18:16:08 +00:00
Joplin Bot
2519b73117 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-12 00:39:18 +00:00
Laurent Cozic
639bfc4533 Desktop release v2.14.9 2024-01-11 21:31:48 +00:00
Henry Heino
97a04ea9e3 Chore: Merge release-2.13 into dev (#9698)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-01-11 21:22:52 +00:00
Henry Heino
150ee7631e Desktop,Mobile,Cli: Fixes #8891: Fix AWS S3 sync error (#9696) 2024-01-11 21:22:42 +00:00
Joplin Bot
9a68157b86 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-10 12:19:57 +00:00
Laurent Cozic
12878672e4 Doc: Improve Plans page documentation 2024-01-10 12:11:28 +00:00
Laurent Cozic
15f019789b Doc: Added documentation for custom publishing banner 2024-01-10 12:03:45 +00:00
Laurent Cozic
311905f6d2 Doc: Add documentation for share permission feature 2024-01-10 11:53:26 +00:00
Laurent Cozic
a74035c22f Doc: Add documentation for Teams feature 2024-01-10 11:49:39 +00:00
Joplin Bot
361e56e9b4 Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-10 00:39:38 +00:00
Laurent Cozic
04fa761258 Desktop release v2.14.8 2024-01-09 22:05:58 +00:00
Laurent Cozic
b2109dab99 Desktop: Resolves #9693: Allow importing a directory of ENEX files 2024-01-09 22:03:34 +00:00
Joplin Bot
61a3962eda Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-09 18:15:01 +00:00
Laurent Cozic
97af8cb7f5 Chore: Refactor sidebar utilities to TypeScript 2024-01-09 16:25:13 +00:00
Henry Heino
17bdec22ca Chore: Fix test plugin update script missing several recently-added plugins (#9691) 2024-01-09 15:13:24 +00:00
Joplin Bot
1d176b31ff Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-08 12:20:31 +00:00
Henry Heino
32e76d7988 Desktop: Resolves #9683: Frontmatter importer: Support Notesnook-style timestamps (#9684) 2024-01-08 11:59:44 +00:00
Henry Heino
94e3582bb8 Chore: Fixes #9678: Fix API and mobile startup regressions caused by folder refactor (#9679) 2024-01-08 11:58:11 +00:00
Henry Heino
b9b2d37fdd Desktop: Update Simple Backup to v1.3.5 to fix some notebooks exported twice while creating a backup (#9677) 2024-01-08 11:57:50 +00:00
Xavi Lee
a465d0ee8d Chore: turndown-plugin-gfm: Fix package name in README (#9674)
Co-authored-by: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com>
2024-01-08 11:56:09 +00:00
renovate[bot]
a29666d442 Update dependency react-native-device-info to v10.12.0 (#9687)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-08 11:53:58 +00:00
renovate[bot]
d3ccb9786b Update actions/checkout action to v4 (#9688)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-08 11:53:46 +00:00
renovate[bot]
2625f0d89e Update dependency fs-extra to v11.2.0 (#9686)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-08 11:53:28 +00:00
Laurent Cozic
1cd0c3742e Doc: Clean-up coding style and added section about unit testing 2024-01-08 11:43:11 +00:00
Laurent Cozic
2e94b01700 Desktop release v2.14.7 2024-01-08 10:52:42 +00:00
Laurent Cozic
20b1c2e7cb Desktop, Cli: Fix ENEX import issue
Ref: https://discourse.joplinapp.org/t/error-importing-notes-from-format-enex/35001
2024-01-08 10:51:46 +00:00
renovate[bot]
4e8863d81f Update dependency sharp to v0.33.1 (#9685)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-08 07:59:08 +00:00
renovate[bot]
a34a911b1e Update dependency tap to v16.3.10 (#9664)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-08 05:21:47 +00:00
Joplin Bot
2bf2395f1b Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-07 12:18:58 +00:00
renovate[bot]
a6b150e63a Update dependency react-native-vector-icons to v10.0.3 (#9663)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-07 09:09:14 +00:00
renovate[bot]
50a7b21f8d Update dependency @types/react-redux to v7.1.33 (#9662)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-07 09:04:15 +00:00
Arda Kılıçdağı
76e8186858 All: Translation: Update tr_TR.po (#9672) 2024-01-06 12:44:49 -05:00
Laurent Cozic
763716397b Chore: Refactor folder related functions to TypeScript 2024-01-06 17:21:51 +00:00
Laurent Cozic
68e04f944f Chore: TypeScript tweaks 2024-01-06 16:37:15 +00:00
Laurent Cozic
91b51adc48 Chore: Fixed VSCode rendering issue due to strange template 2024-01-06 16:33:57 +00:00
github-actions[bot]
4c12c25bd8 @awxiaoxian2020 has signed the CLA in laurent22/joplin#9674 2024-01-06 16:18:19 +00:00
Laurent Cozic
c0dcf1d3e3 iOS 12.14.2 2024-01-06 12:47:34 +00:00
Laurent Cozic
efa35d9317 lock file 2024-01-06 12:47:27 +00:00
Laurent Cozic
3c210a012a Android 2.14.3 2024-01-06 12:45:54 +00:00
Laurent Cozic
92667bafc1 Desktop release v2.14.6 2024-01-06 12:19:13 +00:00
Henry Heino
fc7d053521 Chore: Webclipper: Migrate build system to Webpack 5 (#9670) 2024-01-06 12:15:10 +00:00
Henry Heino
47072b3813 Chore: Migrate from css to @adobe/css-tools (#9660)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-01-06 12:13:23 +00:00
Henry Heino
7a13003af5 Chore: Mobile: Allow debugging iOS WebViews when running in dev mode (#9659)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2024-01-06 12:13:00 +00:00
charles
723b708d89 All: Translation: Update zh_TW.po (#9650) 2024-01-05 20:36:46 -05:00
Laurent Cozic
36a24a5ed8 Chore: Add more tests for tags 2024-01-05 18:21:24 +00:00
Laurent Cozic
091bf4a3d7 Fix tests 2024-01-05 18:16:09 +00:00
Laurent Cozic
ce8e5e61be Chore: Convert tag tests to TypeScript 2024-01-05 16:40:58 +00:00
Laurent Cozic
b8462c4754 Fixed rename 2024-01-05 15:03:23 +00:00
Laurent Cozic
73ad7e0572 Chore: Added test for OCR search 2024-01-05 14:43:24 +00:00
Laurent Cozic
2bf4f39ca1 Chore: Moved search files from "searchengine" namespace to just "search" 2024-01-05 14:15:47 +00:00
Laurent Cozic
29b8fcd5bb Chore: Converted search engine tests to TypeScript 2024-01-05 14:06:33 +00:00
renovate[bot]
2a96012577 Update dependency deprecated-react-native-prop-types to v5 (#9666)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-05 11:56:56 +00:00
Laurent Cozic
474e8c95a0 Chore: Make buildScriptIndexes generates code that passes linter 2024-01-05 09:46:53 +00:00
Laurent Cozic
906b7c3a33 Chore: Allow saving multiple note changes in one transaction 2024-01-05 09:38:22 +00:00
renovate[bot]
0a2afdb010 Update dependency react-native-paper to v5.11.4 (#9639)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-05 02:43:42 +00:00
Laurent Cozic
a281163353 Chore: Automatically build migration index 2024-01-04 17:18:57 +00:00
Laurent Cozic
9aa7240d5e Doc: Added documentation for OCR 2024-01-04 16:25:58 +00:00
Laurent Cozic
9cf63168da Doc: Added documentation for OCR 2024-01-04 16:18:03 +00:00
Henry Heino
430f73c47a Desktop,Mobile: Resolves #9594: Fix table-of-contents links to headings with duplicate content (#9610) 2024-01-04 15:14:52 +00:00
Henry Heino
7e8c87e908 Desktop: Resolves #9468: Add support for changing text colors in rich text editor (#9578) 2024-01-04 13:51:26 +00:00
Henry Heino
4e09b6f2a4 Desktop,Mobile: Resolves #3201: Render mermaid diagrams in dark mode when Joplin is in dark mode (#9631) 2024-01-04 13:45:06 +00:00
github-actions[bot]
d02058d337 @charles7668 has signed the CLA in laurent22/joplin#9650 2024-01-04 00:29:12 +00:00
Laurent Cozic
f95ee689fd Mobile: Improve sync by reducing how often note list is sorted 2024-01-03 18:02:05 +00:00
ERYpTION
164e53ee7d All: Translation: Update da_DK.po (#9640) 2024-01-01 08:05:00 -05:00
Joplin Bot
cb1322f01e Doc: Auto-update documentation
Auto-updated using release-website.sh
2024-01-01 00:42:45 +00:00
Joplin Bot
cc22d71408 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-31 18:15:57 +00:00
Laurent Cozic
ff7c13ac85 Android 2.14.2 2023-12-31 16:41:40 +00:00
Laurent Cozic
302bc4dcc7 Desktop release v2.14.5 2023-12-31 16:06:59 +00:00
Laurent Cozic
ebfc5da0fe Chore: Fix sync issue with Joplin Server when DELTA_INCLUDES_ITEMS is disabled 2023-12-31 16:06:02 +00:00
Laurent Cozic
00eee19077 Desktop, Cli: Fix importing certain ENEX notes that include invalid tables 2023-12-31 15:07:12 +00:00
Laurent Cozic
4048d83dd7 Tools: Exclude some packages from git-changelog 2023-12-31 00:24:30 +00:00
renovate[bot]
48b8fae625 Update dependency ts-node to v10.9.2 (#9622)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-12-31 00:16:08 +00:00
Laurent Cozic
60fbc6e022 Update renovate.json5 2023-12-31 00:15:39 +00:00
renovate[bot]
ae73b5b87c Update dependency react-native-get-random-values to v1.10.0 (#9635)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-31 00:14:39 +00:00
renovate[bot]
6bc2ef9869 Update dependency rate-limiter-flexible to v3.0.6 (#9633)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-30 20:17:43 +00:00
renovate[bot]
206d4ab56d Update dependency @types/react to v18.2.43 (#9632)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-30 20:12:59 +00:00
Helmut K. C. Tessarek
96456aa851 Update translations 2023-12-30 21:12:31 +01:00
rnbastos
adf0ccee2f All: Translation: Update pt_BR.po (#9627) 2023-12-30 15:02:10 -05:00
Mr.X
01394e43d9 All: Translation: Update zh_CN.po (#9609) 2023-12-30 15:00:11 -05:00
Laurent Cozic
39c19db69c Desktop release v2.14.4 2023-12-30 19:21:43 +00:00
Laurent Cozic
105e408dca Chore: Fixed OCR error handling 2023-12-30 19:20:50 +00:00
Laurent Cozic
37dbea1613 Chore: Add more types to synchronizer and improved sync conflict log 2023-12-30 19:05:41 +00:00
Laurent Cozic
2512adebd2 Desktop release v2.14.3 2023-12-30 16:55:06 +00:00
Laurent Cozic
28538de028 Chore: Desktop: Trying to fix OCR 2023-12-30 16:54:51 +00:00
Laurent Cozic
a0b4f5acac iOS 12.14.1 2023-12-29 23:10:40 +00:00
Laurent Cozic
30a5bda5b9 lock file 2023-12-29 22:23:26 +00:00
Laurent Cozic
c5865b3bf5 Android 2.14.1 2023-12-29 22:21:20 +00:00
Laurent Cozic
a9f6b38120 Desktop release v2.14.2 2023-12-29 21:13:28 +00:00
Laurent Cozic
75447f7267 Chore: Trying to fix macOS notarization 2023-12-29 21:13:15 +00:00
Laurent Cozic
ca703adf6a Desktop release v2.14.1 2023-12-29 18:49:15 +00:00
Laurent Cozic
f38abc5718 Server: Display correct date and time on published notes 2023-12-29 18:42:34 +00:00
Henry Heino
d733a7f5ae Chore: Fix flaky mermaid/KaTeX rendering test (#9628) 2023-12-29 17:58:07 +00:00
rnbastos
0f388b13c7 Update index.md (#9626) 2023-12-29 16:50:59 +00:00
Laurent Cozic
754ca39926 Desktop: Fixes #9511: HTML notes are not readable in dark mode 2023-12-29 16:08:09 +00:00
github-actions[bot]
8a05baa97f @rnbastos has signed the CLA in laurent22/joplin#9626 2023-12-29 13:19:28 +00:00
renovate[bot]
1df00a1e5a Update dependency @react-native-community/slider to v4.4.4 (#9620)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-29 05:57:20 +00:00
renovate[bot]
5e63b623ca Update dependency @playwright/test to v1.40.1 (#9621)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-29 05:56:46 +00:00
renovate[bot]
f8a25cb275 Update dependency @types/react-redux to v7.1.32 (#9616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-28 15:06:24 +00:00
renovate[bot]
1e866ead3e Update dependency @playwright/test to v1.40.0 (#9618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-28 14:52:45 +00:00
renovate[bot]
3970b0876d Update dependency knex to v3 (#9619)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-28 14:52:14 +00:00
renovate[bot]
6b711f655d Update dependency @types/react to v18.2.42 (#9615)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-28 12:00:35 +00:00
Laurent Cozic
65d3ed0c67 Update renovate.json5 2023-12-28 11:29:33 +00:00
renovate[bot]
512e37b46a Update dependency tesseract.js to v5.0.3 (#9600)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-28 09:12:06 +00:00
renovate[bot]
ed15b5e5da Update dependency nodemon to v3.0.2 (#9599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-28 09:07:56 +00:00
github-actions[bot]
f9d1157266 @ZhReimu has signed the CLA in laurent22/joplin#9609 2023-12-27 14:14:54 +00:00
Naoki Kawamukai
cda0538681 All: Translation: Update ja_JP.po (#9604) 2023-12-26 18:56:46 -05:00
Laurent Cozic
3342b138b4 Update renovate.json5 2023-12-26 12:53:54 +00:00
Laurent Cozic
9285bb7a88 Update renovate.json5 2023-12-26 12:53:24 +00:00
Laurent Cozic
590769b1ae Desktop, Cli: Resolves #9596: Restore note links after importing an ENEX file 2023-12-26 11:59:26 +00:00
Joplin Bot
0873b1900b Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-25 18:15:47 +00:00
Joplin Bot
5df499e6c7 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-25 12:18:47 +00:00
github-actions[bot]
d89c686555 @tinyoverflow has signed the CLA in laurent22/joplin#9603 2023-12-25 01:41:09 +00:00
Joplin Bot
d81497f7b8 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-25 00:39:52 +00:00
renovate[bot]
8cd377013e Update dependency @types/react to v18.2.41 (#9598)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-24 19:12:56 +00:00
Henry Heino
c623d98bda Desktop: Fixes #9586: Fix code blocks with blank lines break tables in the rich text editor (#9587) 2023-12-24 14:56:08 +00:00
Henry Heino
02232c0ca3 Mobile: Fixes #9502: Fix note editor crash when trying to edit text quickly after opening a note (#9581) 2023-12-24 14:54:24 +00:00
Henry Heino
8ae3210378 Chore: Desktop: Add Playwright test for mermaid and KaTeX rendering (#9583) 2023-12-24 14:50:22 +00:00
Laurent Cozic
bf907f21c4 Desktop, Cli: Fixes #9548: Import ENEX archives that contain files with invalid names 2023-12-24 11:24:48 +00:00
Laurent Cozic
cec5f1f3ba Desktop: Resolves #9261: Mention in sync wizard that Dropbox and OneDrive are slow on first sync 2023-12-24 11:06:28 +00:00
Laurent Cozic
b4928eb7e5 Chore: Mobile: Fixed regression that would prevent the app from running on Android 7 2023-12-23 22:38:02 +00:00
Laurent Cozic
3dcbb2ed51 Chore: Refactor BaseModel queries 2023-12-23 22:38:01 +00:00
Joplin Bot
e744cf0171 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-23 15:14:47 +00:00
Laurent Cozic
1ffafdcefc Doc: Added news item "Faster synchronisation in upcoming Joplin version" 2023-12-23 15:05:23 +00:00
Joplin Bot
e48303aeb7 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-23 14:44:45 +00:00
Laurent Cozic
fb13e0ca80 Doc: Added news item "Faster synchronisation in upcoming Joplin version" 2023-12-23 14:33:10 +00:00
Laurent Cozic
7345cd4678 Chore: Refactor sync target code to allow labels and descriptions to be translated 2023-12-23 14:19:06 +00:00
Laurent Cozic
5341501d53 Desktop, Cli, Mobile, Server: Optimise synchronisation by making delta call return whole items 2023-12-23 13:13:50 +00:00
renovate[bot]
1fcfa9c591 Update dependency tesseract.js to v5 (#9575)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-12-22 21:20:29 +00:00
Joplin Bot
1cd2d9254f Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-22 18:16:15 +00:00
Henry Heino
ee18271f9b Desktop: Resolves #7934: Don't create an extra copy of default plugins (load directly from the app bundle) (#9508) 2023-12-22 11:31:57 +00:00
Laurent Cozic
bf59b23efe Merge branch 'release-2.13' into dev 2023-12-22 09:40:28 +00:00
Laurent Cozic
973193623a Desktop release v2.13.10 2023-12-22 09:30:38 +00:00
Laurent Cozic
495f088320 Desktop, Cli: Remove unnecessary warning when importing ENEX file 2023-12-22 09:30:17 +00:00
Laurent Cozic
d264bdd14d Desktop, Cli: Fixed importing invalid tables from ENEX files 2023-12-22 09:29:53 +00:00
Henry Heino
144ec1eea2 Desktop: Fixes #9543: Fix nested tables not preserved in rich text editor (#9579) 2023-12-22 09:27:20 +00:00
Joplin Bot
7d60bfc192 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-21 18:15:00 +00:00
renovate[bot]
b5428ddc2a Update dependency style-to-js to v1.1.10 (#9574)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 15:14:25 +00:00
renovate[bot]
2075626d42 Update dependency @types/tar-stream to v3.1.3 (#9573)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-21 15:14:13 +00:00
Joplin Bot
4b9307015e Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-21 12:19:02 +00:00
Laurent Cozic
9c88cb2151 Merge pull request #9559 from personalizedrefrigerator/pr/merge-release-2-13
Chore: Merge release 2.13
2023-12-20 19:14:21 +00:00
renovate[bot]
45dcca865d Update dependency @types/tar-stream to v3 (#9568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 19:11:22 +00:00
renovate[bot]
c421a5a732 Update dependency react-select to v5.8.0 (#9567)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 19:11:01 +00:00
renovate[bot]
f7158f5e27 Update dependency react-native-paper to v5.11.3 (#9566)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 19:10:45 +00:00
renovate[bot]
780c269e14 Update dependency ldapts to v7.0.7 (#9565)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 19:10:38 +00:00
Henry Heino
5eb0cda8b9 Desktop,Mobile: Resolves #9562: CodeMirror 6 markdown editor: Support highlighting more languages (#9563) 2023-12-20 19:10:20 +00:00
Henry Heino
3b4eb16110 Desktop: Fixes #9045: Ubuntu: Fix window sometimes doesn't appear on startup (#9561) 2023-12-20 19:09:28 +00:00
Henry Heino
674bbf9667 Chore: Website: Use only one commit per website update (#9558) 2023-12-20 19:08:57 +00:00
Henry Heino
f7e64e9681 Chore: iOS: Remove now-unnecessary scrolling non-root element (#9554) 2023-12-20 19:08:28 +00:00
Henry Heino
4ec2fb216e Chore: Cli: Migrate most commands to TypeScript (#9552) 2023-12-20 19:08:07 +00:00
pedr
ddebeb68b2 Chore: Add function exports to lib/uuid module (#9560) 2023-12-20 19:05:59 +00:00
renovate[bot]
8b09d71d5b Update react monorepo (#9538)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 19:05:35 +00:00
renovate[bot]
3df499714b Update dependency @types/node to v18.18.14 (#9564)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-20 16:34:53 +00:00
Henry Heino
6e9ff89dda Merge remote-tracking branch 'upstream/release-2.13' into pr/merge-release-2-13 2023-12-19 10:23:05 -08:00
github-actions[bot]
880215acc4 @NavyStack has signed the CLA in laurent22/joplin#9550 2023-12-18 01:29:40 +00:00
Henry Heino
d4157e14fe Mobile: Fixes #9532: Fix cursor location on opening the editor and attachments inserted in wrong location (#9536) 2023-12-17 20:58:22 +00:00
Henry Heino
b237a92e02 Mobile: Fixes #9322: Fix editor scrollbar on iOS (#9531) 2023-12-17 20:57:40 +00:00
Henry Heino
0bd164642e Desktop: Fixes #9528: Fix maximum width setting not respected by beta editor (#9529) 2023-12-17 20:57:12 +00:00
Henry Heino
872fadf454 Desktop,Mobile: Resolves #9526: Make backspace delete auto-matching brackets (#9527) 2023-12-17 20:57:00 +00:00
Henry Heino
404e86cef4 Desktop,Mobile: Fixes #9524: Fix Beta Editor diff highlighting (#9525) 2023-12-17 20:56:46 +00:00
Henry Heino
5f6b2f1a63 Mobile,Desktop: Fixes #9522: Fix code block borders in headers of Beta Markdown editor (#9523) 2023-12-17 20:55:54 +00:00
Henry Heino
858205a72b Chore: Fix plugin website build (#9516) 2023-12-17 20:54:56 +00:00
ERYpTION
dc8ea620a6 All: Translation: Update da_DK.po (#9542) 2023-12-17 13:40:15 -05:00
github-actions[bot]
28527541f5 @ERYpTION has signed the CLA in laurent22/joplin#9542 2023-12-17 16:34:01 +00:00
Mr-Kanister
b1051a3144 All: Translation: Update de_DE.po (#9535) 2023-12-17 10:38:17 -05:00
Laurent Cozic
06639eb399 Server v2.14.1 2023-12-17 15:08:27 +00:00
Laurent Cozic
5e3c12aeb8 Chore: Setup new release 2.14 2023-12-17 15:07:31 +00:00
Laurent Cozic
7e50b117ed Desktop, Cli: Remove unnecessary warning when importing ENEX file 2023-12-17 12:00:05 +00:00
Laurent Cozic
bb47c59414 Chore: Remove warning from test 2023-12-17 11:59:11 +00:00
Laurent Cozic
26459ea9dc Chore: Improve app testing script 2023-12-17 11:29:47 +00:00
Laurent Cozic
67a68709e3 Server: Support including items with delta call to optimise sync 2023-12-17 11:12:26 +00:00
renovate[bot]
d13a3fc5c8 Update dependency npm-package-json-lint to v7.1.0 (#9541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-17 09:53:14 +00:00
renovate[bot]
27b5f59d7c Update dependency @react-native-community/netinfo to v9.5.0 (#9540)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-17 09:53:00 +00:00
Laurent Cozic
6b7c11d694 Update renovate.json5 2023-12-17 09:52:16 +00:00
renovate[bot]
1bf38eff32 Update dependency tesseract.js to v4.1.4 (#9537)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-16 22:27:15 +00:00
Laurent Cozic
c93f22d84b Update renovate.json5 2023-12-16 20:11:33 +00:00
Laurent Cozic
17c25b72f0 Desktop: Include more information when auto-generating import error report 2023-12-16 13:12:00 +00:00
Laurent Cozic
a2ded180cb Desktop, Cli: Fixed importing invalid tables from ENEX files 2023-12-16 12:52:42 +00:00
Laurent Cozic
d6c7902390 Chore: Change Renovate rebase logic 2023-12-16 12:52:41 +00:00
renovate[bot]
167892e383 Update dependency react-native-webview to v13.6.3 (#9519)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-16 09:36:50 +00:00
renovate[bot]
62dd4b9926 Update dependency react-native-paper to v5.11.2 (#9518)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-16 09:36:42 +00:00
renovate[bot]
b19a0761fd Update dependency react-native-image-picker to v7.0.3 (#9517)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-16 09:36:33 +00:00
Laurent Cozic
e47ac1de6a Chore: Disable Jest console wrapper in tests 2023-12-15 18:34:21 +00:00
Laurent Cozic
d2fe33183b Chore: Add more types to export modules 2023-12-15 18:18:11 +00:00
Laurent Cozic
02658370a6 Desktop, Cli: Fixes #9486: When importing a Markdown file that contains a link to an invalid image, import fails 2023-12-15 13:28:09 +00:00
Laurent Cozic
46ed6411c1 Desktop, Cli: Fixes #9485: When importing MarkdownD+FrontMatter files that contain images with a data URL source, the import fails 2023-12-15 12:47:03 +00:00
Laurent Cozic
c333e9c802 Desktop, Cli: Fixes #9483: Markdown-FrontMatter exporter generates invalid file when note starts with a dash in title 2023-12-15 11:54:39 +00:00
renovate[bot]
73617bf019 Update dependency @react-native-community/datetimepicker to v7.6.2 (#9515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-15 06:55:36 +00:00
renovate[bot]
f3038c9cf9 Update dependency @types/node to v18.18.13 (#9510)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-15 02:53:43 +00:00
Henry Heino
0f81b08f89 Chore: Fix plugin website build (#9514) 2023-12-14 20:09:27 +00:00
Joplin Bot
0c34497c78 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-14 18:17:10 +00:00
Laurent Cozic
f244f44c7b Desktop, Cli: Fixes #9484: Fixes issue with resources having no associated files when the RAW import process is interrupted 2023-12-14 17:17:21 +00:00
Laurent Cozic
b11006c3a7 Build artifacts 2023-12-14 16:42:57 +00:00
pedr
d63b84ee1f Chore: Add function to generate secure random values (#9409)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-12-14 15:28:41 +00:00
Joplin Bot
e761b97944 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-14 12:18:26 +00:00
Henry Heino
49cf4d9965 Chore: Website: Include the plugin discovery website on joplinapp.org/ (#9469) 2023-12-14 10:21:36 +00:00
renovate[bot]
3732d3e360 Update dependency @types/node to v18.18.12 (#9493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-14 10:14:31 +00:00
Joplin Bot
62a64ed575 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-14 00:37:22 +00:00
Laurent Cozic
20cb03ab69 Ingore renovate ackage 2023-12-13 20:00:38 +00:00
Laurent Cozic
995423cadf Chore: Wait when Discourse update fails 2023-12-13 20:00:19 +00:00
Henry Heino
a730d349e4 Mobile,Desktop: Fixes #9200: Fix list renumbering and enable multiple selections (#9506) 2023-12-13 19:48:06 +00:00
pedr
6d6f9b3c3b Mobile: Fixes #9500: Fix font for the inbox email address not using the theme color (#9503) 2023-12-13 19:47:26 +00:00
Henry Heino
09b5ef6713 Chore: Desktop: Increase Playwright test timeout by 20s in CI (#9497) 2023-12-13 19:45:58 +00:00
renovate[bot]
e0cc8da884 Update dependency @types/yargs to v17.0.32 (#9495)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-13 19:45:42 +00:00
Henry Heino
d17e36d038 Desktop: Resolves #9480: Cancel showing unresponsive dialog when receiving "responsive" event (#9487) 2023-12-13 19:45:29 +00:00
Henry Heino
815a0a5db4 Mobile: Fixes #9477: Fix inline code at beginning of line in table breaks formatting (#9478) 2023-12-13 19:45:17 +00:00
Henry Heino
19b68102b2 Plugins: Resolves #9473: Expose common CodeMirror 6 packages to plugins (#9474) 2023-12-13 19:45:02 +00:00
pedr
04e0274055 Chore: Server: Remove direct dependecy from nanoid library (#9501) 2023-12-13 19:25:52 +00:00
Laurent Cozic
bce94f1775 Desktop: Add support for OCR (#8975) 2023-12-13 19:24:58 +00:00
renovate[bot]
0e847685ff Update dependency @types/react-redux to v7.1.31 (#9494)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-13 16:48:27 +00:00
renovate[bot]
c008b58712 Update dependency @types/markdown-it to v13.0.7 (#9492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-12 12:11:16 +00:00
Laurent Cozic
de67ec4684 Doc: Add sponsor 2023-12-11 16:53:40 +00:00
renovate[bot]
06bf6b85fe Update dependency @types/koa to v2.13.12 (#9491)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-11 16:26:34 +00:00
Arda Kılıçdağı
0d1529f1ad All: Translation: Update tr_TR.po (#9479) 2023-12-11 09:47:16 -05:00
Henry Heino
4fc786cf0b Desktop: Resolves #7934: Add Simple Backup as a default plugin (#9360) 2023-12-11 13:58:45 +00:00
Laurent Cozic
6306a0f371 Doc: Fixed plugin API doc for note list 2023-12-11 12:08:41 +00:00
Laurent Cozic
45c483263e Chore: Improve note list plugins 2023-12-11 11:28:33 +00:00
renovate[bot]
d50e347f35 Update dependency @types/jsdom to v21.1.6 (#9490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-11 10:32:50 +00:00
Laurent Cozic
913e650bb3 Merge branch 'release-2.13' into dev 2023-12-09 16:51:22 +00:00
Joplin Bot
5e537db538 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-09 12:16:18 +00:00
renovate[bot]
706e7e07d1 Update dependency @types/node to v18.18.10 (#9472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-09 11:08:27 +00:00
Joplin Bot
dc9f732ded Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-09 06:14:45 +00:00
Joplin Bot
cedf84698e Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-09 00:35:59 +00:00
renovate[bot]
9915a59bce Update dependency @rmp135/sql-ts to v1.18.1 (#9470)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-08 21:15:48 +00:00
Laurent Cozic
1bbec445d5 Desktop release v2.13.9 2023-12-08 10:15:26 +00:00
Henry Heino
27a0959f30 Chore: Refactor Note.tsx and note-screen-shared.tsx to improve type safety (#9467) 2023-12-08 10:12:23 +00:00
Joplin Bot
b70589ef56 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-08 06:15:32 +00:00
Joplin Bot
b6039e739a Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-08 00:37:39 +00:00
Henry Heino
7558c2e9fe Plugin Repo: Prevent plugin authors from marking their own plugins as recommended (#9462) 2023-12-07 12:43:38 +00:00
Henry Heino
d63fc524bf Chore: Change the return type of shim.fsDriver() from any to FsDriverBase (#9460) 2023-12-06 19:24:00 +00:00
Henry Heino
48ea014ee0 Chore: Release script: Fix editor package version not updated (#9458) 2023-12-06 19:23:23 +00:00
Henry Heino
fd5a4dcbbf Desktop,Mobile: Fixes #9455: Fix KaTeX rendering (#9456) 2023-12-06 19:23:08 +00:00
Henry Heino
92a0964a8d Desktop: Fixes #9304: Fix HTML resource links lost when editing notes in the rich text editor (#9435) 2023-12-06 19:17:16 +00:00
Laurent Cozic
c0c32a7ac1 Update BUG_REPORT.yml 2023-12-06 19:12:23 +00:00
Laurent Cozic
5cfe945c4e Update BUG_REPORT.yml 2023-12-06 19:11:30 +00:00
dimitristsilis
51f96eb9dd All: Translation: Update el_GR.po (#9454) 2023-12-06 11:42:51 -05:00
github-actions[bot]
f6121bae2b @Harshiths1 has signed the CLA in laurent22/joplin#9457 2023-12-06 16:26:37 +00:00
renovate[bot]
3c40854a8c Update docker/login-action action to v3 (#9428)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-06 10:16:15 +00:00
Henry Heino
b271e54828 Chore: Fixes #9449: Mobile: Fix "useNativeDriver" warning (#9448)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-12-06 10:15:33 +00:00
Laurent Cozic
2c0f8d5c6b Chore: Trying to improve flaky test 2023-12-05 18:53:32 +00:00
Joplin Bot
474365188d Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-05 18:14:45 +00:00
renovate[bot]
80c2a87da2 Update dependency ts-loader to v9.5.1 (#9447)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-05 06:27:24 +00:00
renovate[bot]
a8f0f01826 Update dependency mermaid to v10.6.1 (#9444)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-04 21:30:00 +00:00
renovate[bot]
4bb06cb4a0 Update dependency mermaid to v10.6.0 (#9440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-04 18:00:10 +00:00
Joplin Bot
9d0a862798 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-04 00:37:09 +00:00
renovate[bot]
583c6da970 Update dependency @testing-library/react-native to v12.3.3 (#9437)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-03 21:25:45 +00:00
Laurent Cozic
9a7c737f15 Doc: Minor fix 2023-12-03 20:05:12 +01:00
Joplin Bot
08805f01e7 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-03 18:13:32 +00:00
Laurent Cozic
01cc550adf Doc: Add release 2.13 2023-12-03 14:23:59 +01:00
Joplin Bot
1a250639ca Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-03 12:16:10 +00:00
Laurent Cozic
d610036692 Doc: Add release 2.13 2023-12-03 11:50:12 +01:00
Laurent Cozic
f05307d69f Chore: Improve sharing tests 2023-12-03 11:50:11 +01:00
Laurent Cozic
cc99ec3edf Merge branch 'release-2.13' into dev 2023-12-03 11:37:27 +01:00
Laurent Cozic
604dcbc35b Desktop release v2.13.8 2023-12-03 11:36:37 +01:00
Laurent Cozic
b459ba7224 Desktop: Fixed images not being visible on encrypted published notes 2023-12-03 11:35:46 +01:00
Helmut K. C. Tessarek
aaa1dc853d All: Translation: Update pl_PL.po (thanks Manius71) 2023-12-02 16:46:42 +01:00
github-actions[bot]
cadc974999 @dimitristsilis has signed the CLA in laurent22/joplin#9430 2023-12-01 17:50:43 +00:00
Laurent Cozic
d812cf273f Merge branch 'release-2.13' into dev 2023-12-01 14:50:02 +01:00
Laurent Cozic
0d0398312f iOS 12.13.10 2023-12-01 13:08:37 +01:00
Laurent Cozic
39c8fc812d Android 2.13.10 2023-12-01 13:07:42 +01:00
renovate[bot]
9e89357e64 Update dependency electron-builder to v24.8.0 (#9425)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-01 10:22:34 +00:00
Henry Heino
0638d711d7 Mobile: Resolves #9427: Drawing: Revert recent changes to input system (#9426) 2023-12-01 11:11:14 +01:00
renovate[bot]
dad91594c8 Update eslint (#9424)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-01 07:33:29 +00:00
Joplin Bot
fb77c75520 Doc: Auto-update documentation
Auto-updated using release-website.sh
2023-12-01 00:39:52 +00:00
renovate[bot]
00adf2aced Update dependency react-native-localize to v3.0.4 (#9413)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-30 20:04:05 +01:00
renovate[bot]
aaddc58416 Update dependency @types/styled-components to v5.1.32 (#9412)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-30 20:03:49 +01:00
Laurent Cozic
5092e21067 CLI v2.13.2 2023-11-30 20:02:41 +01:00
Laurent Cozic
388000ded3 Lock file 2023-11-30 20:02:37 +01:00
Laurent Cozic
567c513d83 Releasing sub-packages 2023-11-30 20:01:45 +01:00
Laurent Cozic
1e14dffab0 iOS 12.13.9 2023-11-30 20:01:45 +01:00
Laurent Cozic
ed02a0a900 Android 2.13.9 2023-11-30 20:01:45 +01:00
Henry Heino
f989698998 Mobile: Fixes #9374: Fix tooltips don't disappear on some devices (upgrade to js-draw 1.13.2) (#9401) 2023-11-30 20:01:44 +01:00
Henry Heino
0a75480a32 Mobile: Resolves #9377: Don't attach empty drawings when a user exits without saving (#9386) 2023-11-30 20:01:43 +01:00
renovate[bot]
86b470359d Update dependency rate-limiter-flexible to v3.0.4 (#9422)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-30 18:35:12 +00:00
Laurent Cozic
9bad668cc5 CLI v2.13.2 2023-11-30 19:12:07 +01:00
Laurent Cozic
c18c31ab7f Lock file 2023-11-30 19:10:57 +01:00
Laurent Cozic
7c24a2f4be Releasing sub-packages 2023-11-30 19:10:02 +01:00
Laurent Cozic
56438ea644 iOS 12.13.9 2023-11-30 18:56:49 +01:00
Laurent Cozic
7f9bc1e15c Android 2.13.9 2023-11-30 18:56:17 +01:00
renovate[bot]
6ddae5b654 Update dependency yeoman-generator to v5.10.0 (#9420)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-30 14:49:06 +01:00
pedr
3ee8da0cae Server: Fixes #9367: Redirect user from login to home if already logged (#9415) 2023-11-30 14:39:49 +01:00
renovate[bot]
2fd985b9ac Update react monorepo (#9418)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-30 04:39:07 +00:00
renovate[bot]
3cc87e6acd Update dependency react-native-image-picker to v7.0.2 (#9419)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-30 01:09:53 +00:00
renovate[bot]
ac6c6e9996 Update dependency react-native-image-picker to v7 (#9382)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-11-30 00:12:34 +01:00
renovate[bot]
7c6db44cc7 Update dependency react-native-vector-icons to v10.0.2 (#9417)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-29 21:23:59 +00:00
renovate[bot]
fb7f524415 Update dependency node-cron to v3.0.3 (#9416)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-29 19:07:58 +00:00
pedr
fd4f70f62b Chore: Add enums for ApplicationPlatform and ApplicationType (#9410) 2023-11-29 16:31:49 +01:00
renovate[bot]
afd653ba4d Update dependency @types/zxcvbn to v4.4.4 (#9414)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-29 16:30:49 +01:00
renovate[bot]
9827788176 Update dependency @types/uuid to v9.0.7 (#9411)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-29 16:30:26 +01:00
Henry Heino
b1c8cb5632 Mobile: Fixes #9374: Fix tooltips don't disappear on some devices (upgrade to js-draw 1.13.2) (#9401) 2023-11-29 15:17:29 +01:00
Laurent Cozic
2924bb5437 Chore: Upgrade to sharp 0.33.0 to fix random CI failures 2023-11-29 15:14:09 +01:00
renovate[bot]
7ce954da30 Update dependency @types/react-redux to v7.1.30 (#9407)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-29 00:55:54 +00:00
renovate[bot]
84e8f8b0dc Update dependency react-native-localize to v3.0.3 (#9399)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 19:47:24 +01:00
renovate[bot]
0a2bcf7342 Update dependency @types/styled-components to v5.1.30 (#9408)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 19:43:39 +01:00
renovate[bot]
ddd8b99637 Update dependency @types/yargs to v17.0.31 (#9389)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 19:43:22 +01:00
renovate[bot]
705565e4bf Update dependency @types/nodemailer to v6.4.14 (#9406)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 16:16:38 +00:00
renovate[bot]
92d446e0a3 Update dependency @types/node to v18.18.9 (#9405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 12:20:07 +00:00
renovate[bot]
345c602e07 Update dependency @types/js-yaml to v4.0.9 (#9404)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 11:37:12 +00:00
renovate[bot]
852991f429 Update dependency @types/fs-extra to v11.0.4 (#9403)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 07:47:02 +00:00
renovate[bot]
e2f9e87cdf Update dependency @types/node-rsa to v1.1.4 (#9398)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 03:17:59 +00:00
renovate[bot]
7f0d86a1e5 Update dependency @types/formidable to v3.4.5 (#9400)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-28 01:23:53 +00:00
renovate[bot]
a97cb65bbc Update dependency @types/node-fetch to v2.6.9 (#9397)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 21:42:03 +00:00
renovate[bot]
61d32926e7 Update dependency @types/mustache to v4.2.5 (#9395)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 19:14:28 +00:00
Henry Heino
f0a1b41794 Mobile: Resolves #9377: Don't attach empty drawings when a user exits without saving (#9386) 2023-11-27 20:14:04 +01:00
renovate[bot]
6f902201a9 Update dependency @types/markdown-it to v13.0.6 (#9394)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 18:03:40 +00:00
renovate[bot]
e5ffe3af0f Update dependency @types/koa to v2.13.11 (#9393)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 15:45:18 +00:00
renovate[bot]
54cc4898a4 Update dependency @types/jsdom to v21.1.5 (#9392)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 13:09:57 +00:00
renovate[bot]
414e60aa48 Update dependency @types/react-redux to v7.1.29 (#9388)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 06:38:40 +00:00
renovate[bot]
8869c7b6c2 Update dependency @types/bcryptjs to v2.4.6 (#9390)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-27 04:02:32 +00:00
Laurent Cozic
74f7801f25 Doc: Fixed plugin doc and removed redundant CI check 2023-11-26 23:00:23 +01:00
Laurent Cozic
3c8a8619f9 Doc: Fixes #9384, Fixes #9347, Fixes #9295, Fixes #9362: Redirect old links to new ones 2023-11-26 19:52:21 +01:00
Laurent Cozic
35849b1d34 iOS 12.13.8 2023-11-26 16:45:17 +01:00
Laurent Cozic
306b043b30 Android 2.13.8 2023-11-26 16:45:15 +01:00
Laurent Cozic
0117f23ee4 Desktop release v2.13.7 2023-11-26 16:45:13 +01:00
Laurent Cozic
8c5eaaf65c Mobile: Fixes #9376: Sidebar is not dismissed when creating a note 2023-11-26 16:45:11 +01:00
pedr
529140cf87 Mobile: #9361: Fix to-dos options toggle don't toggle a rerender in (#9364) 2023-11-26 16:45:08 +01:00
Henry Heino
d11bdf586a Mobile: Fixes #9328: Fix new note/to-do buttons not visible on app startup in some cases (#9329) 2023-11-26 16:45:06 +01:00
Laurent Cozic
02982464a6 iOS 12.13.8 2023-11-26 13:55:26 +01:00
renovate[bot]
c103bbce14 Update dependency @types/react to v18.2.36 (#9383)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-26 12:52:14 +00:00
Laurent Cozic
62e317db05 lock file 2023-11-26 13:49:00 +01:00
Laurent Cozic
e0795748a9 Android 2.13.8 2023-11-26 13:40:59 +01:00
renovate[bot]
7936e789c0 Update dependency nanoid to v3.3.7 (#9380)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-26 11:49:55 +00:00
Laurent Cozic
67070ed3d5 Desktop release v2.13.7 2023-11-26 12:38:28 +01:00
Laurent Cozic
fec8c6131c Mobile: Fixes #9376: Sidebar is not dismissed when creating a note 2023-11-26 12:37:45 +01:00
Laurent Cozic
f267d8853b All: Handle Dropbox payload_too_large error 2023-11-26 10:45:43 +01:00
renovate[bot]
46ce792ef2 Update dependency react-native-paper to v5.11.1 (#9372)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-25 21:23:54 +00:00
renovate[bot]
074261862d Update dependency @types/react to v18.2.35 (#9370)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-25 18:40:53 +00:00
renovate[bot]
069c7a6b34 Update dependency react-native-paper to v5.11.0 (#9371)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-25 18:09:06 +01:00
Jia
7272ad771b Translation: Update zh_TW.po (#9369)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
2023-11-25 17:12:50 +01:00
github-actions[bot]
74d66a9f1a @Jia35 has signed the CLA in laurent22/joplin#9369 2023-11-25 06:47:52 +00:00
Laurent Cozic
6244999899 Doc: Document how to build and translate the help pages 2023-11-24 20:02:46 +01:00
Laurent Cozic
9930359210 CI: Fix PR title script (#9366) 2023-11-24 17:03:12 +01:00
pedr
24ed5bda63 Mobile: #9361: Fix to-dos options toggle don't toggle a rerender in (#9364) 2023-11-24 14:48:41 +01:00
Henry Heino
dbb354ad10 Mobile: Fixes #9328: Fix new note/to-do buttons not visible on app startup in some cases (#9329) 2023-11-19 10:43:57 +00:00
752 changed files with 73931 additions and 78953 deletions

View File

@@ -59,6 +59,8 @@ packages/app-mobile/locales
packages/app-mobile/node_modules
packages/app-mobile/pluginAssets/
packages/fork-*
packages/default-plugins/plugin-base-repo/
packages/default-plugins/plugin-sources/
packages/htmlpack/dist/
packages/lib/assets/
packages/lib/lib/lib.js
@@ -84,14 +86,37 @@ packages/lib/countable/Countable.js
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
packages/app-cli/app/LinkSelector.js
packages/app-cli/app/app.js
packages/app-cli/app/base-command.js
packages/app-cli/app/command-apidoc.js
packages/app-cli/app/command-attach.js
packages/app-cli/app/command-cat.js
packages/app-cli/app/command-config.js
packages/app-cli/app/command-cp.js
packages/app-cli/app/command-done.test.js
packages/app-cli/app/command-done.js
packages/app-cli/app/command-dump.js
packages/app-cli/app/command-e2ee.js
packages/app-cli/app/command-edit.js
packages/app-cli/app/command-exit.js
packages/app-cli/app/command-export-sync-status.js
packages/app-cli/app/command-export.js
packages/app-cli/app/command-geoloc.js
packages/app-cli/app/command-help.js
packages/app-cli/app/command-import.js
packages/app-cli/app/command-ls.js
packages/app-cli/app/command-mkbook.test.js
packages/app-cli/app/command-mkbook.js
packages/app-cli/app/command-mv.js
packages/app-cli/app/command-ren.js
packages/app-cli/app/command-rmbook.js
packages/app-cli/app/command-rmnote.js
packages/app-cli/app/command-set.js
packages/app-cli/app/command-settingschema.js
packages/app-cli/app/command-sync.js
packages/app-cli/app/command-testing.js
packages/app-cli/app/command-use.js
packages/app-cli/app/command-version.js
packages/app-cli/app/gui/StatusBarWidget.js
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/setupCommand.js
@@ -222,7 +247,6 @@ packages/app-desktop/gui/Navigator.js
packages/app-desktop/gui/NoteContentPropertiesDialog.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/setupVim.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.test.js
@@ -270,6 +294,7 @@ packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.js
packages/app-desktop/gui/NoteEditor/utils/contextMenu.js
packages/app-desktop/gui/NoteEditor/utils/contextMenuUtils.js
packages/app-desktop/gui/NoteEditor/utils/index.js
packages/app-desktop/gui/NoteEditor/utils/markupRenderOptions.js
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.test.js
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.js
packages/app-desktop/gui/NoteEditor/utils/types.js
@@ -380,13 +405,17 @@ packages/app-desktop/gui/style/StyledTextInput.js
packages/app-desktop/gui/utils/NoteListUtils.js
packages/app-desktop/gui/utils/convertToScreenCoordinates.js
packages/app-desktop/gui/utils/loadScript.js
packages/app-desktop/gulpfile.js
packages/app-desktop/integration-tests/main.spec.js
packages/app-desktop/integration-tests/models/MainScreen.js
packages/app-desktop/integration-tests/models/NoteEditorScreen.js
packages/app-desktop/integration-tests/models/SettingsScreen.js
packages/app-desktop/integration-tests/simpleBackup.spec.js
packages/app-desktop/integration-tests/util/activateMainMenuItem.js
packages/app-desktop/integration-tests/util/createStartupArgs.js
packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.js
packages/app-desktop/integration-tests/util/setFilePickerResponse.js
packages/app-desktop/integration-tests/util/setMessageBoxResponse.js
packages/app-desktop/integration-tests/util/test.js
packages/app-desktop/playwright.config.js
packages/app-desktop/plugins/GotoAnything.js
@@ -414,8 +443,11 @@ packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.js
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
packages/app-desktop/tools/copy7Zip.js
packages/app-desktop/tools/notarizeMacApp.js
packages/app-desktop/tools/renameReleaseAssets.js
packages/app-desktop/utils/7zip/getPathToExecutable7Zip.js
packages/app-desktop/utils/7zip/pathToBundled7Zip.js
packages/app-desktop/utils/checkForUpdatesUtils.test.js
packages/app-desktop/utils/checkForUpdatesUtils.js
packages/app-desktop/utils/checkForUpdatesUtilsTestData.js
@@ -458,10 +490,15 @@ packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToggleSpaceButton.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/Toolbar.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarButton.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarOverflowRows.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useActionButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useHeaderButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useInlineFormattingButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useListButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/types.js
packages/app-mobile/components/NoteEditor/NoteEditor.test.js
packages/app-mobile/components/NoteEditor/NoteEditor.js
packages/app-mobile/components/NoteEditor/SearchPanel.js
packages/app-mobile/components/NoteEditor/hooks/useKeyboardVisible.js
packages/app-mobile/components/NoteEditor/types.js
packages/app-mobile/components/NoteList.js
packages/app-mobile/components/ProfileSwitcher/ProfileEditor.js
@@ -529,21 +566,31 @@ packages/app-mobile/utils/fs-driver/runOnDeviceTests.js
packages/app-mobile/utils/setupNotifications.js
packages/app-mobile/utils/shareHandler.js
packages/app-mobile/utils/types.js
packages/default-plugins/build.js
packages/default-plugins/buildDefaultPlugins.js
packages/default-plugins/commands/buildAll.js
packages/default-plugins/commands/editPatch.js
packages/default-plugins/utils/getCurrentCommitHash.js
packages/default-plugins/utils/getPathToPatchFileFor.js
packages/default-plugins/utils/readRepositoryJson.js
packages/default-plugins/utils/waitForCliInput.js
packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.test.js
packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.js
packages/editor/CodeMirror/CodeMirror5Emulation/Decorator.js
packages/editor/CodeMirror/CodeMirrorControl.test.js
packages/editor/CodeMirror/CodeMirrorControl.js
packages/editor/CodeMirror/PluginLoader.js
packages/editor/CodeMirror/configFromSettings.js
packages/editor/CodeMirror/createEditor.test.js
packages/editor/CodeMirror/createEditor.js
packages/editor/CodeMirror/editorCommands/editorCommands.js
packages/editor/CodeMirror/editorCommands/insertLineAfter.test.js
packages/editor/CodeMirror/editorCommands/insertLineAfter.js
packages/editor/CodeMirror/editorCommands/supportsCommand.js
packages/editor/CodeMirror/editorCommands/swapLine.js
packages/editor/CodeMirror/getScrollFraction.js
packages/editor/CodeMirror/markdown/computeSelectionFormatting.test.js
packages/editor/CodeMirror/markdown/computeSelectionFormatting.js
packages/editor/CodeMirror/markdown/decoratorExtension.test.js
packages/editor/CodeMirror/markdown/decoratorExtension.js
packages/editor/CodeMirror/markdown/markdownCommands.bulletedVsChecklist.test.js
packages/editor/CodeMirror/markdown/markdownCommands.test.js
@@ -554,12 +601,15 @@ packages/editor/CodeMirror/markdown/markdownMathParser.js
packages/editor/CodeMirror/markdown/markdownReformatter.test.js
packages/editor/CodeMirror/markdown/markdownReformatter.js
packages/editor/CodeMirror/markdown/syntaxHighlightingLanguages.js
packages/editor/CodeMirror/pluginApi/PluginLoader.js
packages/editor/CodeMirror/pluginApi/codeMirrorRequire.js
packages/editor/CodeMirror/testUtil/createEditorSettings.js
packages/editor/CodeMirror/testUtil/createTestEditor.js
packages/editor/CodeMirror/testUtil/forceFullParse.js
packages/editor/CodeMirror/testUtil/loadLanguages.js
packages/editor/CodeMirror/theme.js
packages/editor/CodeMirror/util/isInSyntaxNode.js
packages/editor/CodeMirror/util/setupVim.js
packages/editor/SelectionFormatting.js
packages/editor/events.js
packages/editor/types.js
@@ -625,9 +675,11 @@ packages/lib/components/shared/config/shouldShowMissingPasswordWarning.test.js
packages/lib/components/shared/config/shouldShowMissingPasswordWarning.js
packages/lib/components/shared/note-screen-shared.js
packages/lib/components/shared/reduxSharedMiddleware.js
packages/lib/components/shared/side-menu-shared.js
packages/lib/database-driver-better-sqlite.js
packages/lib/database.js
packages/lib/debug/DebugService.js
packages/lib/determineProfileDir.js
packages/lib/dom.js
packages/lib/errorUtils.js
packages/lib/errors.js
@@ -635,7 +687,9 @@ packages/lib/eventManager.js
packages/lib/file-api-driver-joplinServer.js
packages/lib/file-api-driver-memory.js
packages/lib/file-api-driver.test.js
packages/lib/file-api.test.js
packages/lib/file-api.js
packages/lib/folders-screen-utils.js
packages/lib/fs-driver-base.js
packages/lib/fs-driver-node.js
packages/lib/fsDriver.test.js
@@ -652,6 +706,7 @@ packages/lib/import-enex.js
packages/lib/initLib.js
packages/lib/locale.test.js
packages/lib/locale.js
packages/lib/makeDiscourseDebugUrl.test.js
packages/lib/makeDiscourseDebugUrl.js
packages/lib/markdownUtils.test.js
packages/lib/markdownUtils.js
@@ -682,19 +737,23 @@ packages/lib/models/Search.js
packages/lib/models/Setting.test.js
packages/lib/models/Setting.js
packages/lib/models/SmartFilter.js
packages/lib/models/Tag.test.js
packages/lib/models/Tag.js
packages/lib/models/dateTimeFormats.test.js
packages/lib/models/settings/FileHandler.js
packages/lib/models/settings/settingValidations.js
packages/lib/models/utils/isItemId.js
packages/lib/models/utils/itemCanBeEncrypted.js
packages/lib/models/utils/paginatedFeed.js
packages/lib/models/utils/paginationToSql.js
packages/lib/models/utils/readOnly.js
packages/lib/models/utils/resourceUtils.js
packages/lib/models/utils/types.js
packages/lib/models/utils/userData.test.js
packages/lib/models/utils/userData.js
packages/lib/net-utils.js
packages/lib/ntp.js
packages/lib/onedrive-api.test.js
packages/lib/onedrive-api.js
packages/lib/path-utils.js
packages/lib/reducer.js
@@ -737,9 +796,13 @@ packages/lib/services/commands/propsHaveChanged.js
packages/lib/services/commands/stateToWhenClauseContext.js
packages/lib/services/contextkey/contextkey.js
packages/lib/services/database/addMigrationFile.js
packages/lib/services/database/isSqliteSyntaxError.js
packages/lib/services/database/migrations/42.js
packages/lib/services/database/migrations/43.js
packages/lib/services/database/migrations/44.js
packages/lib/services/database/migrations/45.js
packages/lib/services/database/migrations/index.js
packages/lib/services/database/sqlStringToLines.js
packages/lib/services/database/types.js
packages/lib/services/debug/populateDatabase.js
packages/lib/services/e2ee/EncryptionService.test.js
@@ -786,6 +849,13 @@ packages/lib/services/keychain/KeychainServiceDriverBase.js
packages/lib/services/noteList/defaultLeftToRightListRenderer.js
packages/lib/services/noteList/defaultListRenderer.js
packages/lib/services/noteList/renderers.js
packages/lib/services/ocr/OcrDriverBase.js
packages/lib/services/ocr/OcrService.test.js
packages/lib/services/ocr/OcrService.js
packages/lib/services/ocr/drivers/OcrDriverTesseract.js
packages/lib/services/ocr/utils/filterOcrText.test.js
packages/lib/services/ocr/utils/filterOcrText.js
packages/lib/services/ocr/utils/types.js
packages/lib/services/plugins/BasePlatformImplementation.js
packages/lib/services/plugins/BasePluginRunner.js
packages/lib/services/plugins/MenuController.js
@@ -863,15 +933,17 @@ packages/lib/services/rest/utils/paginatedResults.js
packages/lib/services/rest/utils/readonlyProperties.js
packages/lib/services/rest/utils/requestFields.js
packages/lib/services/rest/utils/requestPaginationOptions.js
packages/lib/services/searchengine/SearchEngine.js
packages/lib/services/searchengine/SearchEngineUtils.test.js
packages/lib/services/searchengine/SearchEngineUtils.js
packages/lib/services/searchengine/SearchFilter.test.js
packages/lib/services/searchengine/filterParser.test.js
packages/lib/services/searchengine/filterParser.js
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
packages/lib/services/searchengine/queryBuilder.js
packages/lib/services/search/SearchEngine.resources.test.js
packages/lib/services/search/SearchEngine.test.js
packages/lib/services/search/SearchEngine.js
packages/lib/services/search/SearchEngineUtils.test.js
packages/lib/services/search/SearchEngineUtils.js
packages/lib/services/search/SearchFilter.test.js
packages/lib/services/search/filterParser.test.js
packages/lib/services/search/filterParser.js
packages/lib/services/search/gotoAnythingStyleQuery.test.js
packages/lib/services/search/gotoAnythingStyleQuery.js
packages/lib/services/search/queryBuilder.js
packages/lib/services/share/ShareService.test.js
packages/lib/services/share/ShareService.js
packages/lib/services/share/reducer.js
@@ -905,12 +977,16 @@ packages/lib/services/synchronizer/syncInfoUtils.js
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
packages/lib/services/synchronizer/tools.js
packages/lib/services/synchronizer/utils/checkDisabledSyncItemsNotification.js
packages/lib/services/synchronizer/utils/handleConflictAction.js
packages/lib/services/synchronizer/utils/handleSyncStartupOperation.js
packages/lib/services/synchronizer/utils/resourceRemotePath.js
packages/lib/services/synchronizer/utils/syncDeleteStep.js
packages/lib/services/synchronizer/utils/types.js
packages/lib/shim-init-node.js
packages/lib/shim.js
packages/lib/string-utils.test.js
packages/lib/string-utils.js
packages/lib/testing/syncTargetUtils.js
packages/lib/testing/test-utils-synchronizer.js
packages/lib/testing/test-utils.js
@@ -925,9 +1001,12 @@ packages/lib/themes/solarizedDark.js
packages/lib/themes/solarizedLight.js
packages/lib/themes/type.js
packages/lib/time.js
packages/lib/types.js
packages/lib/utils/credentialFiles.js
packages/lib/utils/joplinCloud.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/replaceUnsupportedCharacters.test.js
packages/lib/utils/replaceUnsupportedCharacters.js
packages/lib/utils/userFetcher.js
packages/lib/utils/webDAVUtils.test.js
packages/lib/utils/webDAVUtils.js
@@ -966,6 +1045,8 @@ packages/plugin-repo-cli/lib/types.js
packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.js
packages/plugin-repo-cli/lib/utils.js
packages/plugin-repo-cli/lib/validateUntrustedManifest.test.js
packages/plugin-repo-cli/lib/validateUntrustedManifest.js
packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/types.js
packages/plugins/ToggleSidebars/src/index.js
@@ -995,13 +1076,15 @@ packages/renderer/MdToHtml/rules/sanitize_html.js
packages/renderer/MdToHtml/rules/source_map.js
packages/renderer/MdToHtml/setupLinkify.js
packages/renderer/MdToHtml/validateLinks.js
packages/renderer/assetsToHeaders.js
packages/renderer/defaultResourceModel.js
packages/renderer/headerAnchor.js
packages/renderer/highlight.js
packages/renderer/htmlUtils.test.js
packages/renderer/htmlUtils.js
packages/renderer/index.js
packages/renderer/noteStyle.js
packages/renderer/pathUtils.js
packages/renderer/types.js
packages/renderer/utils.js
packages/tools/build-release-stats.test.js
packages/tools/build-release-stats.js
@@ -1009,8 +1092,6 @@ packages/tools/build-translation.js
packages/tools/build-welcome.js
packages/tools/buildServerDocker.test.js
packages/tools/buildServerDocker.js
packages/tools/bundleDefaultPlugins.test.js
packages/tools/bundleDefaultPlugins.js
packages/tools/checkIgnoredFiles.js
packages/tools/checkLibPaths.test.js
packages/tools/checkLibPaths.js

View File

@@ -26,8 +26,8 @@ body:
id: version
attributes:
label: "Joplin version"
placeholder: "For example 2.3.6"
description:
placeholder: "For example 1.0.5"
description: Please note that we will close the issue if the exact version is not provided, as we cannot help without this.
validations:
required: true

View File

@@ -20,6 +20,6 @@ If it's not related to any platform (such as a translation, change to the docume
Then please append the issue that you've addressed or fixed. Use "Resolves #123" for new features or improvements and "Fixes #123" for bug fixes.
AND PLEASE READ THE GUIDE: https://github.com/laurent22/joplin/blob/dev/CONTRIBUTING.md
AND PLEASE READ THE GUIDE: https://github.com/laurent22/joplin/blob/dev/readme/dev/index.md
-->
-->

View File

@@ -107,24 +107,13 @@ if [ "$RUN_TESTS" == "1" ]; then
#
# https://stackoverflow.com/questions/38558989
export NODE_OPTIONS="--max-old-space-size=32768"
yarn run test-ci
yarn test-ci
testResult=$?
if [ $testResult -ne 0 ]; then
exit $testResult
fi
fi
# =============================================================================
# Check that the website builder can run without errors
# =============================================================================
if [ "$RUN_TESTS" == "1" ]; then
if [ "$IS_LINUX" == "1" ]; then
echo "Step: Running website builder..."
node packages/tools/website/processDocs.js --env dev
fi
fi
# =============================================================================
# Run linter for pull requests only. We also don't want this to make the desktop
# release randomly fail.
@@ -133,13 +122,13 @@ fi
if [ "$RUN_TESTS" == "1" ]; then
echo "Step: Running linter..."
yarn run linter-ci ./
yarn linter-ci ./
testResult=$?
if [ $testResult -ne 0 ]; then
exit $testResult
fi
yarn run packageJsonLint
yarn packageJsonLint
testResult=$?
if [ $testResult -ne 0 ]; then
exit $testResult
@@ -186,7 +175,7 @@ fi
# =============================================================================
# Check .gitignore and .eslintignore files - they should be updated when
# new TypeScript files are added by running `yarn run updateIgnored`.
# new TypeScript files are added by running `yarn updateIgnored`.
# See coding_style.md
# =============================================================================
@@ -210,7 +199,8 @@ if [ "$RUN_TESTS" == "1" ]; then
echo "Step: Check that the website still builds..."
mkdir -p ../joplin-website/docs
SKIP_SPONSOR_PROCESSING=1 yarn run buildWebsite
ll ../joplin-website/docs/api/references/plugin_api
SKIP_SPONSOR_PROCESSING=1 yarn buildWebsite
testResult=$?
if [ $testResult -ne 0 ]; then
exit $testResult
@@ -263,14 +253,14 @@ if [ "$IS_DESKTOP_RELEASE" == "1" ]; then
# "python" and seems to no longer respect the PYTHON_PATH environment variable.
# We work around this by aliasing python.
alias python=$(which python3)
USE_HARD_LINKS=false yarn run dist
USE_HARD_LINKS=false yarn dist
else
USE_HARD_LINKS=false yarn run dist
USE_HARD_LINKS=false yarn dist
fi
elif [[ $IS_LINUX = 1 ]] && [ "$IS_SERVER_RELEASE" == "1" ]; then
echo "Step: Building Docker Image..."
cd "$ROOT_DIR"
yarn run buildServerDocker --tag-name $GIT_TAG_NAME --push-images --repository $SERVER_REPOSITORY
yarn buildServerDocker --tag-name $GIT_TAG_NAME --push-images --repository $SERVER_REPOSITORY
else
echo "Step: Building but *not* publishing desktop application..."
@@ -284,8 +274,8 @@ else
export CSC_IDENTITY_AUTO_DISCOVERY=false
npm pkg set 'build.mac.identity'=null --json
USE_HARD_LINKS=false yarn run dist --publish=never
USE_HARD_LINKS=false yarn dist --publish=never
else
USE_HARD_LINKS=false yarn run dist --publish=never
USE_HARD_LINKS=false yarn dist --publish=never
fi
fi

View File

@@ -26,7 +26,7 @@ jobs:
sudo apt-get update || true
sudo apt-get install -y libsecret-1-dev
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v2
with:

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: olegtarasov/get-tag@v2.1
- uses: actions/setup-node@v2
with:
@@ -33,6 +33,12 @@ jobs:
# https://yarnpkg.com/getting-started/install
corepack enable
- name: Install macOs dependencies
if: runner.os == 'macOS'
run: |
# Required for building the canvas package
brew install pango
# See github-action-main.yml for explanation
- uses: actions/setup-python@v4
with:
@@ -61,7 +67,7 @@ jobs:
if [[ $GIT_TAG_NAME = v* ]]; then
echo "Building and publishing desktop application..."
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn run dist --mac --arm64
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn dist --mac --arm64
yarn renameReleaseAssets --repo="$GH_REPO" --tag="$GIT_TAG_NAME" --token="$GITHUB_TOKEN"
else
@@ -74,5 +80,5 @@ jobs:
export CSC_IDENTITY_AUTO_DISCOVERY=false
npm pkg set 'build.mac.identity'=null --json
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn run dist --mac --arm64 --publish=never
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn dist --mac --arm64 --publish=never
fi

View File

@@ -2,7 +2,8 @@ name: Check pull request title
on: [pull_request]
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: Slashgear/action-check-pr-title@v4.3.0
with:
regexp: "(Desktop|Mobile|All|Cli|Tools|Chore|Clipper|Server|Android|iOS|Plugins): (Fixes|Resolves) #[0-9]+: .+"
regexp: "(Desktop|Mobile|All|Cli|Tools|Chore|Clipper|Server|Android|iOS|Plugins|CI|Plugin Repo|Doc): (Fixes|Resolves) #[0-9]+: .+"

View File

@@ -59,6 +59,12 @@ jobs:
# testing.
sudo apt-get install -y xvfb
- name: Install macOs dependencies
if: runner.os == 'macOS'
run: |
# Required for building the canvas package
brew install pango
- name: Install Docker Engine
# if: runner.os == 'Linux' && startsWith(github.ref, 'refs/tags/server-v')
if: runner.os == 'Linux'
@@ -75,7 +81,7 @@ jobs:
sudo apt-get update || true
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: olegtarasov/get-tag@v2.1
- uses: actions/setup-node@v2
with:
@@ -92,7 +98,7 @@ jobs:
# Login to Docker only if we're on a server release tag. If we run this on
# a pull request it will fail because the PR doesn't have access to
# secrets
- uses: docker/login-action@v2
- uses: docker/login-action@v3
if: runner.os == 'Linux' && startsWith(github.ref, 'refs/tags/server-v')
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -135,7 +141,7 @@ jobs:
# To ensure that the operations stop on failure, all commands
# should be on one line with "&&" in between.
run: |
yarn install && cd packages/app-desktop && yarn run dist
yarn install && cd packages/app-desktop && yarn dist
# Build and package the Windows app, without publishing it, just to
# verify that the build process hasn't been broken.
@@ -147,7 +153,7 @@ jobs:
SERVER_REPOSITORY: joplin/server
SERVER_TAG_PREFIX: server
run: |
yarn install && cd packages/app-desktop && yarn run dist --publish=never
yarn install && cd packages/app-desktop && yarn dist --publish=never
ServerDockerImage:
needs: pre_job
@@ -174,7 +180,7 @@ jobs:
sudo apt-get update || true
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v2
with:
@@ -191,7 +197,7 @@ jobs:
BUILD_SEQUENCIAL: 1
run: |
yarn install
yarn run buildServerDocker --tag-name server-v0.0.0 --repository joplin/server
yarn buildServerDocker --tag-name server-v0.0.0 --repository joplin/server
# Basic test to ensure that the created build is valid. It should exit with
# code 0 if it works.

107
.gitignore vendored
View File

@@ -66,14 +66,37 @@ docs/**/*.mustache
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
packages/app-cli/app/LinkSelector.js
packages/app-cli/app/app.js
packages/app-cli/app/base-command.js
packages/app-cli/app/command-apidoc.js
packages/app-cli/app/command-attach.js
packages/app-cli/app/command-cat.js
packages/app-cli/app/command-config.js
packages/app-cli/app/command-cp.js
packages/app-cli/app/command-done.test.js
packages/app-cli/app/command-done.js
packages/app-cli/app/command-dump.js
packages/app-cli/app/command-e2ee.js
packages/app-cli/app/command-edit.js
packages/app-cli/app/command-exit.js
packages/app-cli/app/command-export-sync-status.js
packages/app-cli/app/command-export.js
packages/app-cli/app/command-geoloc.js
packages/app-cli/app/command-help.js
packages/app-cli/app/command-import.js
packages/app-cli/app/command-ls.js
packages/app-cli/app/command-mkbook.test.js
packages/app-cli/app/command-mkbook.js
packages/app-cli/app/command-mv.js
packages/app-cli/app/command-ren.js
packages/app-cli/app/command-rmbook.js
packages/app-cli/app/command-rmnote.js
packages/app-cli/app/command-set.js
packages/app-cli/app/command-settingschema.js
packages/app-cli/app/command-sync.js
packages/app-cli/app/command-testing.js
packages/app-cli/app/command-use.js
packages/app-cli/app/command-version.js
packages/app-cli/app/gui/StatusBarWidget.js
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/setupCommand.js
@@ -204,7 +227,6 @@ packages/app-desktop/gui/Navigator.js
packages/app-desktop/gui/NoteContentPropertiesDialog.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/setupVim.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.js
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.test.js
@@ -252,6 +274,7 @@ packages/app-desktop/gui/NoteEditor/utils/clipboardUtils.js
packages/app-desktop/gui/NoteEditor/utils/contextMenu.js
packages/app-desktop/gui/NoteEditor/utils/contextMenuUtils.js
packages/app-desktop/gui/NoteEditor/utils/index.js
packages/app-desktop/gui/NoteEditor/utils/markupRenderOptions.js
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.test.js
packages/app-desktop/gui/NoteEditor/utils/resourceHandling.js
packages/app-desktop/gui/NoteEditor/utils/types.js
@@ -362,13 +385,17 @@ packages/app-desktop/gui/style/StyledTextInput.js
packages/app-desktop/gui/utils/NoteListUtils.js
packages/app-desktop/gui/utils/convertToScreenCoordinates.js
packages/app-desktop/gui/utils/loadScript.js
packages/app-desktop/gulpfile.js
packages/app-desktop/integration-tests/main.spec.js
packages/app-desktop/integration-tests/models/MainScreen.js
packages/app-desktop/integration-tests/models/NoteEditorScreen.js
packages/app-desktop/integration-tests/models/SettingsScreen.js
packages/app-desktop/integration-tests/simpleBackup.spec.js
packages/app-desktop/integration-tests/util/activateMainMenuItem.js
packages/app-desktop/integration-tests/util/createStartupArgs.js
packages/app-desktop/integration-tests/util/firstNonDevToolsWindow.js
packages/app-desktop/integration-tests/util/setFilePickerResponse.js
packages/app-desktop/integration-tests/util/setMessageBoxResponse.js
packages/app-desktop/integration-tests/util/test.js
packages/app-desktop/playwright.config.js
packages/app-desktop/plugins/GotoAnything.js
@@ -396,8 +423,11 @@ packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
packages/app-desktop/services/sortOrder/notesSortOrderUtils.test.js
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
packages/app-desktop/tools/copy7Zip.js
packages/app-desktop/tools/notarizeMacApp.js
packages/app-desktop/tools/renameReleaseAssets.js
packages/app-desktop/utils/7zip/getPathToExecutable7Zip.js
packages/app-desktop/utils/7zip/pathToBundled7Zip.js
packages/app-desktop/utils/checkForUpdatesUtils.test.js
packages/app-desktop/utils/checkForUpdatesUtils.js
packages/app-desktop/utils/checkForUpdatesUtilsTestData.js
@@ -440,10 +470,15 @@ packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToggleSpaceButton.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/Toolbar.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarButton.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/ToolbarOverflowRows.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useActionButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useHeaderButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useInlineFormattingButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/buttons/useListButtons.js
packages/app-mobile/components/NoteEditor/MarkdownToolbar/types.js
packages/app-mobile/components/NoteEditor/NoteEditor.test.js
packages/app-mobile/components/NoteEditor/NoteEditor.js
packages/app-mobile/components/NoteEditor/SearchPanel.js
packages/app-mobile/components/NoteEditor/hooks/useKeyboardVisible.js
packages/app-mobile/components/NoteEditor/types.js
packages/app-mobile/components/NoteList.js
packages/app-mobile/components/ProfileSwitcher/ProfileEditor.js
@@ -511,21 +546,31 @@ packages/app-mobile/utils/fs-driver/runOnDeviceTests.js
packages/app-mobile/utils/setupNotifications.js
packages/app-mobile/utils/shareHandler.js
packages/app-mobile/utils/types.js
packages/default-plugins/build.js
packages/default-plugins/buildDefaultPlugins.js
packages/default-plugins/commands/buildAll.js
packages/default-plugins/commands/editPatch.js
packages/default-plugins/utils/getCurrentCommitHash.js
packages/default-plugins/utils/getPathToPatchFileFor.js
packages/default-plugins/utils/readRepositoryJson.js
packages/default-plugins/utils/waitForCliInput.js
packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.test.js
packages/editor/CodeMirror/CodeMirror5Emulation/CodeMirror5Emulation.js
packages/editor/CodeMirror/CodeMirror5Emulation/Decorator.js
packages/editor/CodeMirror/CodeMirrorControl.test.js
packages/editor/CodeMirror/CodeMirrorControl.js
packages/editor/CodeMirror/PluginLoader.js
packages/editor/CodeMirror/configFromSettings.js
packages/editor/CodeMirror/createEditor.test.js
packages/editor/CodeMirror/createEditor.js
packages/editor/CodeMirror/editorCommands/editorCommands.js
packages/editor/CodeMirror/editorCommands/insertLineAfter.test.js
packages/editor/CodeMirror/editorCommands/insertLineAfter.js
packages/editor/CodeMirror/editorCommands/supportsCommand.js
packages/editor/CodeMirror/editorCommands/swapLine.js
packages/editor/CodeMirror/getScrollFraction.js
packages/editor/CodeMirror/markdown/computeSelectionFormatting.test.js
packages/editor/CodeMirror/markdown/computeSelectionFormatting.js
packages/editor/CodeMirror/markdown/decoratorExtension.test.js
packages/editor/CodeMirror/markdown/decoratorExtension.js
packages/editor/CodeMirror/markdown/markdownCommands.bulletedVsChecklist.test.js
packages/editor/CodeMirror/markdown/markdownCommands.test.js
@@ -536,12 +581,15 @@ packages/editor/CodeMirror/markdown/markdownMathParser.js
packages/editor/CodeMirror/markdown/markdownReformatter.test.js
packages/editor/CodeMirror/markdown/markdownReformatter.js
packages/editor/CodeMirror/markdown/syntaxHighlightingLanguages.js
packages/editor/CodeMirror/pluginApi/PluginLoader.js
packages/editor/CodeMirror/pluginApi/codeMirrorRequire.js
packages/editor/CodeMirror/testUtil/createEditorSettings.js
packages/editor/CodeMirror/testUtil/createTestEditor.js
packages/editor/CodeMirror/testUtil/forceFullParse.js
packages/editor/CodeMirror/testUtil/loadLanguages.js
packages/editor/CodeMirror/theme.js
packages/editor/CodeMirror/util/isInSyntaxNode.js
packages/editor/CodeMirror/util/setupVim.js
packages/editor/SelectionFormatting.js
packages/editor/events.js
packages/editor/types.js
@@ -607,9 +655,11 @@ packages/lib/components/shared/config/shouldShowMissingPasswordWarning.test.js
packages/lib/components/shared/config/shouldShowMissingPasswordWarning.js
packages/lib/components/shared/note-screen-shared.js
packages/lib/components/shared/reduxSharedMiddleware.js
packages/lib/components/shared/side-menu-shared.js
packages/lib/database-driver-better-sqlite.js
packages/lib/database.js
packages/lib/debug/DebugService.js
packages/lib/determineProfileDir.js
packages/lib/dom.js
packages/lib/errorUtils.js
packages/lib/errors.js
@@ -617,7 +667,9 @@ packages/lib/eventManager.js
packages/lib/file-api-driver-joplinServer.js
packages/lib/file-api-driver-memory.js
packages/lib/file-api-driver.test.js
packages/lib/file-api.test.js
packages/lib/file-api.js
packages/lib/folders-screen-utils.js
packages/lib/fs-driver-base.js
packages/lib/fs-driver-node.js
packages/lib/fsDriver.test.js
@@ -634,6 +686,7 @@ packages/lib/import-enex.js
packages/lib/initLib.js
packages/lib/locale.test.js
packages/lib/locale.js
packages/lib/makeDiscourseDebugUrl.test.js
packages/lib/makeDiscourseDebugUrl.js
packages/lib/markdownUtils.test.js
packages/lib/markdownUtils.js
@@ -664,19 +717,23 @@ packages/lib/models/Search.js
packages/lib/models/Setting.test.js
packages/lib/models/Setting.js
packages/lib/models/SmartFilter.js
packages/lib/models/Tag.test.js
packages/lib/models/Tag.js
packages/lib/models/dateTimeFormats.test.js
packages/lib/models/settings/FileHandler.js
packages/lib/models/settings/settingValidations.js
packages/lib/models/utils/isItemId.js
packages/lib/models/utils/itemCanBeEncrypted.js
packages/lib/models/utils/paginatedFeed.js
packages/lib/models/utils/paginationToSql.js
packages/lib/models/utils/readOnly.js
packages/lib/models/utils/resourceUtils.js
packages/lib/models/utils/types.js
packages/lib/models/utils/userData.test.js
packages/lib/models/utils/userData.js
packages/lib/net-utils.js
packages/lib/ntp.js
packages/lib/onedrive-api.test.js
packages/lib/onedrive-api.js
packages/lib/path-utils.js
packages/lib/reducer.js
@@ -719,9 +776,13 @@ packages/lib/services/commands/propsHaveChanged.js
packages/lib/services/commands/stateToWhenClauseContext.js
packages/lib/services/contextkey/contextkey.js
packages/lib/services/database/addMigrationFile.js
packages/lib/services/database/isSqliteSyntaxError.js
packages/lib/services/database/migrations/42.js
packages/lib/services/database/migrations/43.js
packages/lib/services/database/migrations/44.js
packages/lib/services/database/migrations/45.js
packages/lib/services/database/migrations/index.js
packages/lib/services/database/sqlStringToLines.js
packages/lib/services/database/types.js
packages/lib/services/debug/populateDatabase.js
packages/lib/services/e2ee/EncryptionService.test.js
@@ -768,6 +829,13 @@ packages/lib/services/keychain/KeychainServiceDriverBase.js
packages/lib/services/noteList/defaultLeftToRightListRenderer.js
packages/lib/services/noteList/defaultListRenderer.js
packages/lib/services/noteList/renderers.js
packages/lib/services/ocr/OcrDriverBase.js
packages/lib/services/ocr/OcrService.test.js
packages/lib/services/ocr/OcrService.js
packages/lib/services/ocr/drivers/OcrDriverTesseract.js
packages/lib/services/ocr/utils/filterOcrText.test.js
packages/lib/services/ocr/utils/filterOcrText.js
packages/lib/services/ocr/utils/types.js
packages/lib/services/plugins/BasePlatformImplementation.js
packages/lib/services/plugins/BasePluginRunner.js
packages/lib/services/plugins/MenuController.js
@@ -845,15 +913,17 @@ packages/lib/services/rest/utils/paginatedResults.js
packages/lib/services/rest/utils/readonlyProperties.js
packages/lib/services/rest/utils/requestFields.js
packages/lib/services/rest/utils/requestPaginationOptions.js
packages/lib/services/searchengine/SearchEngine.js
packages/lib/services/searchengine/SearchEngineUtils.test.js
packages/lib/services/searchengine/SearchEngineUtils.js
packages/lib/services/searchengine/SearchFilter.test.js
packages/lib/services/searchengine/filterParser.test.js
packages/lib/services/searchengine/filterParser.js
packages/lib/services/searchengine/gotoAnythingStyleQuery.test.js
packages/lib/services/searchengine/gotoAnythingStyleQuery.js
packages/lib/services/searchengine/queryBuilder.js
packages/lib/services/search/SearchEngine.resources.test.js
packages/lib/services/search/SearchEngine.test.js
packages/lib/services/search/SearchEngine.js
packages/lib/services/search/SearchEngineUtils.test.js
packages/lib/services/search/SearchEngineUtils.js
packages/lib/services/search/SearchFilter.test.js
packages/lib/services/search/filterParser.test.js
packages/lib/services/search/filterParser.js
packages/lib/services/search/gotoAnythingStyleQuery.test.js
packages/lib/services/search/gotoAnythingStyleQuery.js
packages/lib/services/search/queryBuilder.js
packages/lib/services/share/ShareService.test.js
packages/lib/services/share/ShareService.js
packages/lib/services/share/reducer.js
@@ -887,12 +957,16 @@ packages/lib/services/synchronizer/syncInfoUtils.js
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
packages/lib/services/synchronizer/tools.js
packages/lib/services/synchronizer/utils/checkDisabledSyncItemsNotification.js
packages/lib/services/synchronizer/utils/handleConflictAction.js
packages/lib/services/synchronizer/utils/handleSyncStartupOperation.js
packages/lib/services/synchronizer/utils/resourceRemotePath.js
packages/lib/services/synchronizer/utils/syncDeleteStep.js
packages/lib/services/synchronizer/utils/types.js
packages/lib/shim-init-node.js
packages/lib/shim.js
packages/lib/string-utils.test.js
packages/lib/string-utils.js
packages/lib/testing/syncTargetUtils.js
packages/lib/testing/test-utils-synchronizer.js
packages/lib/testing/test-utils.js
@@ -907,9 +981,12 @@ packages/lib/themes/solarizedDark.js
packages/lib/themes/solarizedLight.js
packages/lib/themes/type.js
packages/lib/time.js
packages/lib/types.js
packages/lib/utils/credentialFiles.js
packages/lib/utils/joplinCloud.js
packages/lib/utils/processStartFlags.js
packages/lib/utils/replaceUnsupportedCharacters.test.js
packages/lib/utils/replaceUnsupportedCharacters.js
packages/lib/utils/userFetcher.js
packages/lib/utils/webDAVUtils.test.js
packages/lib/utils/webDAVUtils.js
@@ -948,6 +1025,8 @@ packages/plugin-repo-cli/lib/types.js
packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.js
packages/plugin-repo-cli/lib/utils.js
packages/plugin-repo-cli/lib/validateUntrustedManifest.test.js
packages/plugin-repo-cli/lib/validateUntrustedManifest.js
packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/types.js
packages/plugins/ToggleSidebars/src/index.js
@@ -977,13 +1056,15 @@ packages/renderer/MdToHtml/rules/sanitize_html.js
packages/renderer/MdToHtml/rules/source_map.js
packages/renderer/MdToHtml/setupLinkify.js
packages/renderer/MdToHtml/validateLinks.js
packages/renderer/assetsToHeaders.js
packages/renderer/defaultResourceModel.js
packages/renderer/headerAnchor.js
packages/renderer/highlight.js
packages/renderer/htmlUtils.test.js
packages/renderer/htmlUtils.js
packages/renderer/index.js
packages/renderer/noteStyle.js
packages/renderer/pathUtils.js
packages/renderer/types.js
packages/renderer/utils.js
packages/tools/build-release-stats.test.js
packages/tools/build-release-stats.js
@@ -991,8 +1072,6 @@ packages/tools/build-translation.js
packages/tools/build-welcome.js
packages/tools/buildServerDocker.test.js
packages/tools/buildServerDocker.js
packages/tools/bundleDefaultPlugins.test.js
packages/tools/bundleDefaultPlugins.js
packages/tools/checkIgnoredFiles.js
packages/tools/checkLibPaths.test.js
packages/tools/checkLibPaths.js

View File

@@ -1,3 +1,5 @@
packages/app-clipper/popup/
packages/app-cli/tests/support/plugins/
packages/doc-builder/
packages/doc-builder/
packages/default-plugins/plugin-base-repo/
packages/default-plugins/plugin-sources/

View File

@@ -0,0 +1,62 @@
diff --git a/android/src/newarch/java/com/reactnativecommunity/slider/ReactSliderManager.java b/android/src/newarch/java/com/reactnativecommunity/slider/ReactSliderManager.java
index a5bb95eec3337b93a2338a2869a2bda176c91cae..87817688eb280c2f702c26dc35558c6a0a4db1ea 100644
--- a/android/src/newarch/java/com/reactnativecommunity/slider/ReactSliderManager.java
+++ b/android/src/newarch/java/com/reactnativecommunity/slider/ReactSliderManager.java
@@ -42,12 +42,20 @@ public class ReactSliderManager extends SimpleViewManager<ReactSlider> implement
public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) {
ReactSlider slider = (ReactSlider)seekbar;
- if(progress < slider.getLowerLimit()) {
- progress = slider.getLowerLimit();
- seekbar.setProgress(progress);
- } else if (progress > slider.getUpperLimit()) {
- progress = slider.getUpperLimit();
- seekbar.setProgress(progress);
+ // During initialization, lowerLimit can be greater than upperLimit.
+ //
+ // If a change event is received during this, we need a check to prevent
+ // infinite recursion.
+ //
+ // Issue: https://github.com/callstack/react-native-slider/issues/571
+ if (slider.getLowerLimit() <= slider.getUpperLimit()) {
+ if(progress < slider.getLowerLimit()) {
+ progress = slider.getLowerLimit();
+ seekbar.setProgress(progress);
+ } else if (progress > slider.getUpperLimit()) {
+ progress = slider.getUpperLimit();
+ seekbar.setProgress(progress);
+ }
}
ReactContext reactContext = (ReactContext) seekbar.getContext();
diff --git a/android/src/oldarch/java/com/reactnativecommunity/slider/ReactSliderManager.java b/android/src/oldarch/java/com/reactnativecommunity/slider/ReactSliderManager.java
index 3ff5930f85a3cd92c2549925f41058abb188a57e..ab3681fdfe0b736c97020e1434e450c8183e6f18 100644
--- a/android/src/oldarch/java/com/reactnativecommunity/slider/ReactSliderManager.java
+++ b/android/src/oldarch/java/com/reactnativecommunity/slider/ReactSliderManager.java
@@ -30,12 +30,20 @@ public class ReactSliderManager extends SimpleViewManager<ReactSlider> {
public void onProgressChanged(SeekBar seekbar, int progress, boolean fromUser) {
ReactSlider slider = (ReactSlider)seekbar;
- if(progress < slider.getLowerLimit()) {
- progress = slider.getLowerLimit();
- seekbar.setProgress(progress);
- } else if(progress > slider.getUpperLimit()) {
- progress = slider.getUpperLimit();
- seekbar.setProgress(progress);
+ // During initialization, lowerLimit can be greater than upperLimit.
+ //
+ // If a change event is received during this, we need a check to prevent
+ // infinite recursion.
+ //
+ // Issue: https://github.com/callstack/react-native-slider/issues/571
+ if (slider.getLowerLimit() <= slider.getUpperLimit()) {
+ if(progress < slider.getLowerLimit()) {
+ progress = slider.getLowerLimit();
+ seekbar.setProgress(progress);
+ } else if (progress > slider.getUpperLimit()) {
+ progress = slider.getUpperLimit();
+ seekbar.setProgress(progress);
+ }
}
ReactContext reactContext = (ReactContext) seekbar.getContext();

View File

@@ -0,0 +1,12 @@
diff --git a/package.json b/package.json
index 4f24d9658ca167733dbe9c3fb3bcfc3f4e6d20c8..15062cc4eb3bc8e14b54b07a9c873e5a5c4b6ab8 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,6 @@
"module": "index.js",
"exports": {
".": {
- "browser": "./index.browser.js",
"require": {
"types": "./index.d.cts",
"default": "./index.cjs"

View File

@@ -0,0 +1,15 @@
# We remove the `canvas` optional dependency because electron-rebuild fails to build it, and
# the `canvas` API is already part of Electron
diff --git a/package.json b/package.json
index 105811f53d508486e08a60dc1b6e437cd24d7427..dea6a4e6612c4a4006cc482e46ff5270dcfda1e5 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,6 @@
"bugs": "https://github.com/mozilla/pdf.js/issues",
"license": "Apache-2.0",
"optionalDependencies": {
- "canvas": "^2.11.2",
"path2d-polyfill": "^2.0.1"
},
"browser": {

View File

@@ -23,6 +23,7 @@ module.exports = {
return `joplin.${camelCaseToDots(p)
.replace(/menu\.items/, 'menuItems')
.replace(/toolbar\.buttons/, 'toolbarButtons')
.replace(/note\.list/, 'noteList')
.replace(/content\.scripts/, 'contentScripts')}`;
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -1,4 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Joplin]]></title><description><![CDATA[Joplin, the open source note-taking application]]></description><link>https://joplinapp.org</link><generator>RSS for Node</generator><lastBuildDate>Mon, 23 Oct 2023 00:00:00 GMT</lastBuildDate><atom:link href="https://joplinapp.org/rss.xml" rel="self" type="application/rss+xml"/><pubDate>Mon, 23 Oct 2023 00:00:00 GMT</pubDate><item><title><![CDATA[Working in the shadows with white-hat hackers]]></title><description><![CDATA[<p>The majority of Joplin's development is carried out in the public domain. This includes the discussion of issues on GitHub, as well as the submission of pull requests and related discussions. The transparency of these processes allows for collaborative problem-solving and shared insights.</p>
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Joplin]]></title><description><![CDATA[Joplin, the open source note-taking application]]></description><link>https://joplinapp.org</link><generator>RSS for Node</generator><lastBuildDate>Sat, 27 Jan 2024 00:00:00 GMT</lastBuildDate><atom:link href="https://joplinapp.org/rss.xml" rel="self" type="application/rss+xml"/><pubDate>Sat, 27 Jan 2024 00:00:00 GMT</pubDate><item><title><![CDATA[Support for new plugin metadata]]></title><description><![CDATA[<p>The plugin manifest now supports new properties to better describe and present your plugins on Joplin Plugins website. Those are the <code>icons</code>, <code>categories</code>, <code>screenshots</code> and <code>promo_tile</code> properties.</p>
<h2>Icon<a name="icon" href="#icon" class="heading-anchor">🔗</a></h2>
<p>This is the icon that will be used in various plugin pages, including in your main plugin page. It will be shown on the main result page too. If not provided, a default icon will be displayed instead.</p>
<h2>Category<a name="category" href="#category" class="heading-anchor">🔗</a></h2>
<p>You can supply one or more category for your plugin - it will be used to filter the plugins on the website.</p>
<h2>Screenshots<a name="screenshots" href="#screenshots" class="heading-anchor">🔗</a></h2>
<p>Again you can provide one or more screenshots to present your plugin on the website.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20240127-icon-category-screenshot.png" alt=""></p>
<p><em>An example of plugin with icon, category and screenshot</em></p>
<h2>Promo tile<a name="promo-tile" href="#promo-tile" class="heading-anchor">🔗</a></h2>
<p>The promo tile is an optional image that is used to display your plugin on the main website page. If no promo tile is supplied, the icon will be used instead.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20240127-promo-tile.png" alt=""></p>
<p><em>An example of promo tile</em></p>
<h2>More information<a name="more-information" href="#more-information" class="heading-anchor">🔗</a></h2>
<p>For more information on how to set this plugin metadata, please check the <a href="https://joplinapp.org/help/api/references/plugin_manifest">Plugin Manifest documentation</a></p>
]]></description><link>https://joplinapp.org/news/20240127-new-plugin-metadata</link><guid isPermaLink="false">20240127-new-plugin-metadata</guid><pubDate>Sat, 27 Jan 2024 00:00:00 GMT</pubDate><twitter-text></twitter-text></item><item><title><![CDATA[Faster synchronisation in upcoming Joplin version!]]></title><description><![CDATA[<p>The next version of Joplin Cloud (and Joplin Server) will include a change that will make synchronisation, in particular when synchronising a new device for the first time, significantly faster. This is achieved by bundling more data with the calls that retrieve notes and other data, thus reducing the number of unnecessary requests.</p>
<p>This change will be applied soon to Joplin Cloud (and Server), and the Joplin mobile, desktop and CLI applications will be able to use it from version 2.14.</p>
<p>In my tests with about 26,000 items, synchronisation was more than twice as fast on Joplin Cloud (22.5 minutes vs 9.5 minutes):</p>
<h2>Before<a name="before" href="#before" class="heading-anchor">🔗</a></h2>
<p>Created local items: 21814. Fetched items: 26591/26591. Completed: 23/12/2023 10:38 (<strong>1346s</strong>)</p>
<p><strong>real 22m35.810s</strong><br/><br>
user 3m19.182s<br/><br>
sys 1m24.207s</p>
<h2>Optimised<a name="optimised" href="#optimised" class="heading-anchor">🔗</a></h2>
<p>Created local items: 21822. Fetched items: 26600/26600. Completed: 23/12/2023 11:48 (<strong>571s</strong>)</p>
<p><strong>real 9m38.932s</strong><br/><br>
user 1m10.119s<br/><br>
sys 0m38.013s</p>
]]></description><link>https://joplinapp.org/news/20231223-faster-sync</link><guid isPermaLink="false">20231223-faster-sync</guid><pubDate>Sat, 23 Dec 2023 00:00:00 GMT</pubDate><twitter-text>Faster synchronisation in upcoming Joplin version!</twitter-text></item><item><title><![CDATA[What's new in Joplin 2.13]]></title><description><![CDATA[<h2>Desktop<a name="desktop" href="#desktop" class="heading-anchor">🔗</a></h2>
<h3>Rich Text Editor improvements<a name="rich-text-editor-improvements" href="#rich-text-editor-improvements" class="heading-anchor">🔗</a></h3>
<p>In this update, significant enhancements have been implemented in the Rich Text Editor to enhance user experience. One notable improvement is the ability to seamlessly embed various content within tables, including lists and other tables, which was a frequently requested feature:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20231203-rte-table.png" alt=""></p>
<p>The interoperability with other text editors such as Word and Excel has also been improved, in particular when copying and pasting content between these tools and Joplin.</p>
<h3>Improved ENEX import<a name="improved-enex-import" href="#improved-enex-import" class="heading-anchor">🔗</a></h3>
<p>The Evernote Export format, known as ENEX, has always been challenging to support. This is because Evernote frequently changes it, breaking importers, and may also occasionally introduce bugs. At times, their own application struggles to import back files that it has exported, highlighting the volatility of the ENEX format.</p>
<p>After undergoing continuous improvements for seven years, the importer has achieved a relatively stable state. The majority of issues encountered now stem from invalid files generated by Evernote, a result of bugs introduced in recent versions. Despite these challenges, we strive to enhance the import process by employing various heuristics to process the invalid data as effectively as possible.</p>
<p>The list of bug fixes is below:</p>
<ul>
<li>Apply correct size to images imported from ENEX files</li>
<li>ENEX files that contain resources with invalid mime types are imported correctly</li>
<li>Ensure that ENEX resources with invalid filenames are imported correctly</li>
<li>Prevent application from being stuck when importing an invalid ENEX file</li>
</ul>
<h3>New plugins APIs<a name="new-plugins-apis" href="#new-plugins-apis" class="heading-anchor">🔗</a></h3>
<h4>Note list<a name="note-list" href="#note-list" class="heading-anchor">🔗</a></h4>
<p>We are continuously improving the plugin API to make it as easy as possible to customize the application.</p>
<p>One of the main addition is support note list plugins - it allows any plugins to customise what the list should display each note.</p>
<p>See the <a href="https://joplinapp.org/api/references/plugin_api/classes/joplinviewsnotelist.html">Joplin Plugin Note List API</a> and the <a href="https://github.com/laurent22/joplin/blob/dev/packages/app-cli/tests/support/plugins/note_list_renderer/src/index.ts">Note List Demo</a> for more information.</p>
<p>The demo includes three examples of note lists: a fundamental &quot;top to bottom&quot; version, a sophisticated &quot;left to right&quot; variant that additionally displays a note thumbnail, and a demonstration of an interactive note list, allowing direct modification of the note title from the list.</p>
<p>This API was developed based on the feedback we got and we hope it will be useful. We remain open to further input from users and plugin developers regarding any potential missing features and areas for improvement!</p>
<h4>Imaging API<a name="imaging-api" href="#imaging-api" class="heading-anchor">🔗</a></h4>
<p>The imaging API was created to allow plugin developers to easily load and manipulate images. For now it is possible to load PNG and JPG files, and to resize and crop them.</p>
<p><a href="https://joplinapp.org/api/references/plugin_api/classes/joplinimaging.html">https://joplinapp.org/api/references/plugin_api/classes/joplinimaging.html</a></p>
<h4>And more<a name="and-more" href="#and-more" class="heading-anchor">🔗</a></h4>
<p>A few more APIs have been added such as one to <a href="https://joplinapp.org/api/references/plugin_api/classes/joplinviewsdialogs.html#showopendialog">open dialog to select a file or folder</a> and a way to <a href="https://joplinapp.org/api/references/plugin_api/enums/contentscripttype.html#getting-the-settings-from-the-renderer">access the plugin settings from a renderer script</a>.</p>
<h3>New beta Markdown editor<a name="new-beta-markdown-editor" href="#new-beta-markdown-editor" class="heading-anchor">🔗</a></h3>
<p>This version also features a new Markdown editor based on <a href="https://codemirror.net/">CodeMirror 6</a>. This change means that we'll be able to use the same editor on both the desktop and mobile application (which already uses CodeMirror 6), which will allow a more consistent user experience across devices.</p>
<p>Another benefit is that, in a future version, it will allow us to support plugins on the mobile application. There are several other advantages that Henry <a href="https://discourse.joplinapp.org/t/pre-release-v2-13-is-now-available-updated-18-11-2023/32697/12?u=laurent">listed in this forum post</a>.</p>
<h2>Mobile<a name="mobile" href="#mobile" class="heading-anchor">🔗</a></h2>
<h3>Drawing option<a name="drawing-option" href="#drawing-option" class="heading-anchor">🔗</a></h3>
<p>In this new version, Henry integrated the js-draw editor to the mobile app. Js-draw is a powerful freehand drawing library which allows you to draw using a pen, touch screen or mouse.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20231203-drawing.png" alt=""></p>
<p>The editor is integrated to the mobile application. On desktop application, you can use the same library and edit your drawings using the <a href="https://github.com/personalizedrefrigerator/joplin-plugin-freehand-drawing">Freehand Drawing plugin</a>. We will make this plugin available by default in a future desktop release.</p>
<h3>Setting screen<a name="setting-screen" href="#setting-screen" class="heading-anchor">🔗</a></h3>
<p>The mobile version also features a redesigned configuration screen. It is now divided into multiple sections with clear titles, and you can also search for settings using the built-in search option.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20231203-settings.png" alt=""></p>
<h1>Full changelog<a name="full-changelog" href="#full-changelog" class="heading-anchor">🔗</a></h1>
<p>This is just an overview of the main features. The full changelog is available there:</p>
<ul>
<li>Desktop: <a href="https://joplinapp.org/help/about/changelog/desktop">https://joplinapp.org/help/about/changelog/desktop</a></li>
<li>Android: <a href="https://joplinapp.org/help/about/changelog/android/">https://joplinapp.org/help/about/changelog/android/</a></li>
<li>iOS: <a href="https://joplinapp.org/help/about/changelog/ios/">https://joplinapp.org/help/about/changelog/ios/</a></li>
</ul>
]]></description><link>https://joplinapp.org/news/20231204-release-2-13</link><guid isPermaLink="false">20231204-release-2-13</guid><pubDate>Mon, 04 Dec 2023 00:00:00 GMT</pubDate><twitter-text>What&apos;s new in Joplin 2.13</twitter-text></item><item><title><![CDATA[Working in the shadows with white-hat hackers]]></title><description><![CDATA[<p>The majority of Joplin's development is carried out in the public domain. This includes the discussion of issues on GitHub, as well as the submission of pull requests and related discussions. The transparency of these processes allows for collaborative problem-solving and shared insights.</p>
<p>However, there is one aspect that operates behind closed doors, and for good reason: addressing cybersecurity vulnerabilities. It is imperative that these issues remain undisclosed until they have been resolved. Once a solution is implemented, it is usually accompanied by discreet commits and a message in the changelog to signify the progress made.</p>
<p>Typically, the process begins with an email from a security researcher. They provide valuable insights, such as a specially crafted note that triggers a bug, or an API call, along with an explanation of how the application's security can be circumvented. We examine the vulnerability, create a fix, and create automated test units to prevent any accidental reintroduction of the vulnerability in future code updates. An example of such a commit is: <a href="https://github.com/laurent22/joplin/commit/9e90d9016daf79b5414646a93fd369aedb035071">9e90d9016daf79b5414646a93fd369aedb035071</a></p>
<p>We then share our fix with the researcher for validation. Additionally, we often apply the fix to previous versions of Joplin, depending on the severity of the vulnerability.</p>
@@ -26,7 +99,7 @@
<p>In this release, we've undertaken numerous enhancements and addressed various bugs in the Rich Text editor. Notably, we've introduced support for plugin toolbar icons. Additionally, we've refined the editor's ability to manage text that's copied from applications like Word, Office, and LibreOffice, thereby enhancing cross-application compatibility. Among the minor yet impactful improvements, we've fine-tuned the handling of newlines and paragraphs—a highly requested feature. Another notable update is the improved automatic switching between light and dark modes.</p>
<p>Altogether, this release encompasses around 12 significant changes for the Rich Text editor, and rest assured, there's more to come in the future!</p>
<h3>Share permissions<a name="share-permissions" href="#share-permissions" class="heading-anchor">🔗</a></h3>
<p>Using Joplin Cloud Pro and Teams, you now have the ability to customize the read and write permissions for the notebooks you share. You have the option to grant other users permission to edit the notes or share them as read-only. This ensures that you can confidently share a notebook without worrying about unintentional modifications by your friends or colleagues.</p>
<p>Using Joplin Cloud Teams, you now have the ability to customize the read and write permissions for the notebooks you share. You have the option to grant other users permission to edit the notes or share them as read-only. This ensures that you can confidently share a notebook without worrying about unintentional modifications by your friends or colleagues.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20230825-share-permissions.png" alt=""></p>
<h3>Email to Note<a name="email-to-note" href="#email-to-note" class="heading-anchor">🔗</a></h3>
<p>Joplin Cloud Pro and Teams also now include the Email to Note feature, allowing you to conveniently store your emails within Joplin Cloud. By simply forwarding your emails to your Joplin Cloud address, you can transform them into notes. The email's subject will serve as the note title, while the body of the email will be the note's content. These notes will be organized within a notebook named &quot;Inbox.&quot;</p>
@@ -291,53 +364,4 @@
<p>In the coming month (<strong>March 7 - April 3</strong>), contributors will start getting involved in the forum and start discussing project ideas with the mentors and community. It's also a good time to start looking at Joplin's source code, perhaps work on fixing bugs or implement small features to get familiar with the source code, and to show us your skills.</p>
<p>One difference with previous years is that anyone, not just students, are allowed to participate.</p>
<p>Additionally, last year Google only allowed smaller projects, while this year they allow again small and large projects, so we've indicated this in the idea list - the small ones are <strong>175 hours</strong>, and the large ones <strong>350 hours</strong>.</p>
]]></description><link>https://joplinapp.org/news/20220308-gsoc2022-start</link><guid isPermaLink="false">20220308-gsoc2022-start</guid><pubDate>Tue, 08 Mar 2022 00:00:00 GMT</pubDate><twitter-text></twitter-text></item><item><title><![CDATA[Joplin 2.7 is available!]]></title><description><![CDATA[<p>This new release is largely focused on bug fixing and optimising various parts of the apps. There's about 26 improvements and 25 bugs and security fixes included - as always many of these apply to both the mobile and desktop app (see the <a href="https://joplinapp.org/help/about/changelog/desktop">desktop changelog</a> and <a href="https://joplinapp.org/help/about/changelog/android/">mobile changelog</a>).</p>
<p>Many thanks to all the contributors who helped create this release!</p>
<p>Below are some of the more noticeable changes:</p>
<h2>Notebook custom icons<a name="notebook-custom-icons" href="#notebook-custom-icons" class="heading-anchor">🔗</a></h2>
<p>Since version 2.6 it was possible to assign an emoji icon to a notebook, and with this new version it's now possible to assign any custom icon. The icon may be a PNG or JPG file of any size. The app will then import the file and resize it to the correct size. To use a custom icon, follow these steps:</p>
<p>Right-click on a notebook, and select &quot;Edit&quot;:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20220224-edit-notebook.png" alt=""></p>
<p>In the &quot;Edit notebook&quot; dialog, click &quot;Select file...&quot; and browse to your icon image:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20220224-edit-dialog.png" alt=""></p>
<p>Click &quot;OK&quot; and the icon will now appear next to the notebook:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20220224-notebook-icon.png" alt=""></p>
<p>The icon can be changed only from the desktop application at the moment, but it will sync and be displayed correctly on the mobile app too.</p>
<h2>Plugin API improvements<a name="plugin-api-improvements" href="#plugin-api-improvements" class="heading-anchor">🔗</a></h2>
<p>This version also includes a number of improvements to the plugin API, in particular it is now easier to customise the editor context menu from a plugin and dynamically add items to it depending on the context. For example, with the Rich Markdown plugin it will be possible to right-click on an image and open it, or copy it to the clipboard.</p>
<p>A few additional functions have also been added to make plugin development simpler - in particular a command to open any item, whether it's a notebook, note, tag or attachement; and functions to work with attachements, in particular to reveal an attachement in the system file explorer, and to track changes to an attachement.</p>
]]></description><link>https://joplinapp.org/news/20220224-release-2-7</link><guid isPermaLink="false">20220224-release-2-7</guid><pubDate>Thu, 24 Feb 2022 00:00:00 GMT</pubDate><twitter-text></twitter-text></item><item><title><![CDATA[Automatic deletion of disabled accounts on Joplin Cloud]]></title><description><![CDATA[<p>As of 15 Feb 2022, disabled accounts on Joplin Cloud will be automatically deleted after 90 days. A disabled account is one where the Stripe subscription has been cancelled either by the user or automatically (eg for unpaid invoices).</p>
<p>Although it is an automated system, I will manually verify each account that's queued for deletion over the next few days for additional safety (for now everything's working as expected).</p>
<p>When an account is queued for deletion, all notes, notebooks, tags, etc are removed from the system within 2 days, and permanently deleted within 7 days. User information, in particular email and full name will be removed from the system within 2 days, but archived for an additional 90 days for legal reasons, after which they will be deleted too.</p>
]]></description><link>https://joplinapp.org/news/20220215-142000</link><guid isPermaLink="false">20220215-142000</guid><pubDate>Tue, 15 Feb 2022 00:00:00 GMT</pubDate><twitter-text></twitter-text></item><item><title><![CDATA[Joplin 2.6 is available!]]></title><description><![CDATA[<p>Many changes in this new release, available on mobile, desktop and CLI:</p>
<p><strong>Per-notebook sort order and sort buttons</strong></p>
<p>This new feature adds a number of changes to the way notes are sorted. The most visible one is the addition of a sort button above the note list - it allows sorting by modification date, creation date, title or by custom order, in either ascending or descending order:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20211217-120324_0.png" alt=""></p>
<p>By default, this sort order is going to apply to all notebooks, however you can now also assign a per-notebook sort order. In this case, any sort order will be apply to that notebook only. To enable this behaviour, simply right-click on a notebook and select &quot;Toggle own sort order&quot;:</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20211217-120324_1.png" alt=""></p>
<p>Thanks to Kenichi Kobayashi for developing this feature!</p>
<p><strong>Support for notebook icons</strong></p>
<p>It is now possible to associate icons with notebooks no both the desktop and mobile applications. To do so, right-click on a notebook and selected &quot;Edit&quot;.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20211217-120324_2.png" alt=""></p>
<p>This will open the new notebook dialog from which can change the title and assign an icon. For now the icons are emojis but perhaps custom icons could be supported later on.</p>
<p><img src="https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/news/20211217-120324_3.png" alt=""></p>
<p><strong>Allow collaborating on encrypted notebooks using Joplin Cloud</strong></p>
<p>Thanks to the encryption improvements in the previous Joplin versions it is now possible to share and collaborated on encrypted notebooks, when synchronising with Joplin Cloud (or Joplin Server).</p>
<p>To get this working, you and the recipient will need to have Joplin 2.6 and the person who shares will need to have encryption enabled. After that most of the process is handled automatically by the apps - in particular it will automatically generate and share the required encryption keys for each users.</p>
<p><strong>Improved synchronisation startup speed</strong></p>
<p>Synchronisation is also a bit faster in this release due to an optimisation on the startup process. When syncing, the app needs to acquire a lock, which may be time consuming since it requires making multiple requests. This has now been optimised so that less requests are necessary and also each request consumes less resources. This will have a postive impact on Joplin Cloud in particular, but you should also see improvements with Joplin Server and smaller improvements with the other sync targets.</p>
<p><strong>Improved Markdown editor split view scrolling</strong></p>
<p>Kenichi Kobayashi made some great improvements to the Markdown editor scrolling in this release. The issue before was that the editor on the left and the viewer on the right would often not be in sync, in particular if the note contains several images and other media.</p>
<p>With Kenichi's change the editor and viewer stay nicely in sync, regardless of the note content. In fact it looks a bit like magic when you scroll through large notes - notice in particular how each side appear to wait for the other or speed up in order to make sure both sides are aligned as well possible. Kenichi provides a nice technical documentation about the feature <a href="https://github.com/laurent22/joplin/pull/5512#issuecomment-931277022">here</a>.</p>
<p><a href="https://www.youtube.com/watch?v=Wbs5XZR0oeU">https://www.youtube.com/watch?v=Wbs5XZR0oeU</a></p>
<p><strong>Improved and optimised S3 synchronisation</strong></p>
<p>Thanks to the efforts of Lee Matos, synchronisation with S3 is now more reliable and errors are also better handled. The underlying S3 SDK has also been upgraded from v2 to v3 which results in a smaller executable size (about 3-5 MB depending on the operating system)</p>
<p><strong>Export notes as self-contained HTML files</strong></p>
<p>Exporting a single note as HTML is now more user friendly as all images, scripts, styles and other attachments are all packed into a single HTML file (Previously it would create multiples files and directories). This makes it easier to share the complete note with someone who doesn't have Joplin.</p>
<p><strong>Other changes and bug fixes</strong></p>
<p>This release includes a total of 19 new features and improvements and 16 bug fixes. See the 2.6.x changelogs for more details:</p>
<p><a href="https://joplinapp.org/help/about/changelog/desktop">https://joplinapp.org/help/about/changelog/desktop</a></p>
<p><a href="https://joplinapp.org/help/about/changelog/android/">https://joplinapp.org/help/about/changelog/android/</a></p>
<p><a href="https://joplinapp.org/help/about/changelog/ios/">https://joplinapp.org/help/about/changelog/ios/</a></p>
<p><a href="https://joplinapp.org/help/about/changelog/cli/">https://joplinapp.org/help/about/changelog/cli/</a></p>
]]></description><link>https://joplinapp.org/news/20211217-120324</link><guid isPermaLink="false">20211217-120324</guid><pubDate>Fri, 17 Dec 2021 12:03:24 GMT</pubDate><twitter-text></twitter-text></item></channel></rss>
]]></description><link>https://joplinapp.org/news/20220308-gsoc2022-start</link><guid isPermaLink="false">20220308-gsoc2022-start</guid><pubDate>Tue, 08 Mar 2022 00:00:00 GMT</pubDate><twitter-text></twitter-text></item></channel></rss>

View File

@@ -5,62 +5,64 @@ set -e
trap 'handleError' ERR
handleError() {
echo ""
echo "If you encountered an error, please consider fixing"
echo "the script for your environment and creating a pull"
echo "request instead of asking for support on GitHub or"
echo "the forum. The error message above should tell you"
echo "where and why the error happened."
echo ""
echo "If you encountered an error, please consider fixing"
echo "the script for your environment and creating a pull"
echo "request instead of asking for support on GitHub or"
echo "the forum. The error message above should tell you"
echo "where and why the error happened."
}
#-----------------------------------------------------
# Variables
#-----------------------------------------------------
COLOR_RED=`tput setaf 1`
COLOR_GREEN=`tput setaf 2`
COLOR_YELLOW=`tput setaf 3`
COLOR_BLUE=`tput setaf 4`
COLOR_RESET=`tput sgr0`
# Only set colors, if tput available and TERM is recognized
if [[ `command -v tput` && `tput setaf 1 2>/dev/null` ]]; then
COLOR_RED=`tput setaf 1`
COLOR_GREEN=`tput setaf 2`
COLOR_YELLOW=`tput setaf 3`
COLOR_BLUE=`tput setaf 4`
COLOR_RESET=`tput sgr0`
fi
SILENT=false
ALLOW_ROOT=false
SHOW_CHANGELOG=false
INCLUDE_PRE_RELEASE=false
print() {
if [[ "${SILENT}" == false ]] ; then
echo -e "$@"
fi
if [[ "${SILENT}" == false ]]; then
echo -e "$@"
fi
}
showLogo() {
print "${COLOR_BLUE}"
print " _ _ _ "
print " | | ___ _ __ | (_)_ __ "
print " _ | |/ _ \| '_ \| | | '_ \ "
print "| |_| | (_) | |_) | | | | | |"
print " \___/ \___/| .__/|_|_|_| |_|"
print " |_|"
print ""
print "Linux Installer and Updater"
print "${COLOR_RESET}"
print "${COLOR_BLUE}"
print " _ _ _ "
print " | | ___ _ __ | (_)_ __ "
print " _ | |/ _ \| '_ \| | | '_ \ "
print "| |_| | (_) | |_) | | | | | |"
print " \___/ \___/| .__/|_|_|_| |_|"
print " |_|"
print ""
print "Linux Installer and Updater"
print "${COLOR_RESET}"
}
showHelp() {
showLogo
print "Available Arguments:"
print "\t" "--help" "\t" "Show this help information" "\n"
print "\t" "--allow-root" "\t" "Allow the install to be run as root"
print "\t" "--changelog" "\t" "Show the changelog after installation"
print "\t" "--force" "\t" "Always download the latest version"
print "\t" "--silent" "\t" "Don't print any output"
print "\t" "--prerelease" "\t" "Check for new Versions including Pre-Releases"
if [[ ! -z $1 ]]; then
print "\n" "${COLOR_RED}ERROR: " "$*" "${COLOR_RESET}" "\n"
else
exit 0
fi
showLogo
print "Available Arguments:"
print "\t" "--help" "\t" "Show this help information" "\n"
print "\t" "--allow-root" "\t" "Allow the install to be run as root"
print "\t" "--changelog" "\t" "Show the changelog after installation"
print "\t" "--force" "\t" "Always download the latest version"
print "\t" "--silent" "\t" "Don't print any output"
print "\t" "--prerelease" "\t" "Check for new Versions including Pre-Releases"
if [[ ! -z $1 ]]; then
print "\n" "${COLOR_RED}ERROR: " "$*" "${COLOR_RESET}" "\n"
else
exit 0
fi
}
#-----------------------------------------------------
@@ -71,9 +73,9 @@ optspec=":h-:"
while getopts "${optspec}" OPT; do
[ "${OPT}" = " " ] && continue
if [ "${OPT}" = "-" ]; then # long option: reformulate OPT and OPTARG
OPT="${OPTARG%%=*}" # extract long option name
OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty)
OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=`
OPT="${OPTARG%%=*}" # extract long option name
OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty)
OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=`
fi
case "${OPT}" in
h | help ) showHelp ;;
@@ -90,8 +92,8 @@ shift $((OPTIND-1)) # remove parsed options and args from $@ list
## Check and warn if running as root.
if [[ $EUID = 0 ]] && [[ "${ALLOW_ROOT}" != true ]]; then
showHelp "It is not recommended (nor necessary) to run this script as root. To do so anyway, please use '--allow-root'"
exit 1
showHelp "It is not recommended (nor necessary) to run this script as root. To do so anyway, please use '--allow-root'"
exit 1
fi
#-----------------------------------------------------
@@ -104,12 +106,12 @@ print "Checking architecture..."
## uname actually gives more information than needed, but it contains all architectures (hardware and software)
ARCHITECTURE=$(uname -m -p -i || echo "NO CHECK")
if [[ $ARCHITECTURE = "NO CHECK" ]] ; then
if [[ $ARCHITECTURE = "NO CHECK" ]]; then
print "${COLOR_YELLOW}WARNING: Can't get system architecture, skipping check${COLOR_RESET}"
elif [[ $ARCHITECTURE =~ .*aarch.*|.*arm.* ]] ; then
elif [[ $ARCHITECTURE =~ .*aarch.*|.*arm.* ]]; then
showHelp "Arm systems are not officially supported by Joplin, please search the forum (https://discourse.joplinapp.org/) for more information"
exit 1
elif [[ $ARCHITECTURE =~ .*i386.*|.*i686.* ]] ; then
elif [[ $ARCHITECTURE =~ .*i386.*|.*i686.* ]]; then
showHelp "32-bit systems are not supported by Joplin, please search the forum (https://discourse.joplinapp.org/) for more information"
exit 1
fi
@@ -122,7 +124,7 @@ if [[ $(command -v ldconfig) ]]; then
else
LIBFUSE=$(find /lib /usr/lib /lib64 /usr/lib64 /usr/local/lib -name "libfuse.so.2" 2>/dev/null | grep "libfuse.so.2" || echo '')
fi
if [[ $LIBFUSE == "" ]] ; then
if [[ $LIBFUSE == "" ]]; then
print "${COLOR_RED}Error: Can't get libfuse2 on system, please install libfuse2${COLOR_RESET}"
print "See https://joplinapp.org/help/faq/#desktop-application-will-not-launch-on-linux and https://github.com/AppImage/AppImageKit/wiki/FUSE for more information"
exit 1
@@ -141,17 +143,17 @@ fi
# Check if it's in the latest version
if [[ -e ~/.joplin/VERSION ]] && [[ $(< ~/.joplin/VERSION) == "${RELEASE_VERSION}" ]]; then
print "${COLOR_GREEN}You already have the latest version${COLOR_RESET} ${RELEASE_VERSION} ${COLOR_GREEN}installed.${COLOR_RESET}"
([[ "$FORCE" == true ]] && print "Forcing installation...") || exit 0
print "${COLOR_GREEN}You already have the latest version${COLOR_RESET} ${RELEASE_VERSION} ${COLOR_GREEN}installed.${COLOR_RESET}"
([[ "$FORCE" == true ]] && print "Forcing installation...") || exit 0
else
[[ -e ~/.joplin/VERSION ]] && CURRENT_VERSION=$(< ~/.joplin/VERSION)
print "The latest version is ${RELEASE_VERSION}, but you have ${CURRENT_VERSION:-no version} installed."
[[ -e ~/.joplin/VERSION ]] && CURRENT_VERSION=$(< ~/.joplin/VERSION)
print "The latest version is ${RELEASE_VERSION}, but you have ${CURRENT_VERSION:-no version} installed."
fi
# Check if it's an update or a new install
DOWNLOAD_TYPE="New"
if [[ -f ~/.joplin/Joplin.AppImage ]]; then
DOWNLOAD_TYPE="Update"
DOWNLOAD_TYPE="Update"
fi
#-----------------------------------------------------
@@ -183,8 +185,7 @@ mv "${TEMP_DIR}/joplin.png" ~/.local/share/icons/hicolor/512x512/apps/joplin.png
print "${COLOR_GREEN}OK${COLOR_RESET}"
# Detect desktop environment
if [ "$XDG_CURRENT_DESKTOP" = "" ]
then
if [ "$XDG_CURRENT_DESKTOP" = "" ]; then
DESKTOP=$(echo "${XDG_DATA_DIRS}" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
else
DESKTOP=$XDG_CURRENT_DESKTOP
@@ -210,8 +211,7 @@ if command -v lsb_release &> /dev/null; then
# uses these to sandbox processes. Unfortunately, it doesn't look like we can get around this
# without writing the AppImage to a non-user-writable location (without invalidating other security
# controls). See https://discourse.joplinapp.org/t/possible-future-requirement-for-no-sandbox-flag-for-ubuntu-23-10/.
if [[ $DISTVER = "Ubuntu23.10" || $DISTVER =~ Debian1. || ( "$DISTVER" = "Linuxmint4" && "$DISTCODENAME" = "debbie" ) || ( "$DISTVER" = "CentOS" && "$DISTMAJOR" =~ 6|7 ) ]]
then
if [[ $DISTVER = "Ubuntu23.10" || $DISTVER =~ Debian1. || ( "$DISTVER" = "Linuxmint4" && "$DISTCODENAME" = "debbie" ) || ( "$DISTVER" = "CentOS" && "$DISTMAJOR" =~ 6|7 ) ]]; then
SANDBOXPARAM="--no-sandbox"
print "${COLOR_YELLOW}WARNING${COLOR_RESET} Electron sandboxing disabled."
print " See https://discourse.joplinapp.org/t/32160/5 for details."
@@ -222,41 +222,40 @@ fi
# `.local/share/desktop` had a desktop file created.
# However some environments don't return a desktop BUT still support these desktop files
# the command check was added to support all Desktops that have support for the
# freedesktop standard
# freedesktop standard
# The old checks are left in place for historical reasons, but
# NO MORE DESKTOP ENVIRONMENTS SHOULD BE ADDED
# If a new environment needs to be supported, then the command check section should be re-thought
if [[ $DESKTOP =~ .*gnome.*|.*kde.*|.*xfce.*|.*mate.*|.*lxqt.*|.*unity.*|.*x-cinnamon.*|.*deepin.*|.*pantheon.*|.*lxde.*|.*i3.*|.*sway.* ]] || [[ `command -v update-desktop-database` ]]
then
DATA_HOME=${XDG_DATA_HOME:-~/.local/share}
DESKTOP_FILE_LOCATION="$DATA_HOME/applications"
# Only delete the desktop file if it will be replaced
rm -f "$DESKTOP_FILE_LOCATION/appimagekit-joplin.desktop"
if [[ $DESKTOP =~ .*gnome.*|.*kde.*|.*xfce.*|.*mate.*|.*lxqt.*|.*unity.*|.*x-cinnamon.*|.*deepin.*|.*pantheon.*|.*lxde.*|.*i3.*|.*sway.* ]] || [[ `command -v update-desktop-database` ]]; then
DATA_HOME=${XDG_DATA_HOME:-~/.local/share}
DESKTOP_FILE_LOCATION="$DATA_HOME/applications"
# Only delete the desktop file if it will be replaced
rm -f "$DESKTOP_FILE_LOCATION/appimagekit-joplin.desktop"
# On some systems this directory doesn't exist by default
mkdir -p "$DESKTOP_FILE_LOCATION"
# Tabs specifically, and not spaces, are needed for indentation with Bash heredocs
cat >> "$DESKTOP_FILE_LOCATION/appimagekit-joplin.desktop" <<-EOF
[Desktop Entry]
Encoding=UTF-8
Name=Joplin
Comment=Joplin for Desktop
Exec=${HOME}/.joplin/Joplin.AppImage ${SANDBOXPARAM} %u
Icon=joplin
StartupWMClass=Joplin
Type=Application
Categories=Office;
MimeType=x-scheme-handler/joplin;
X-GNOME-SingleWindow=true // should be removed eventually as it was upstream to be an XDG specification
SingleMainWindow=true
EOF
# Update application icons
[[ `command -v update-desktop-database` ]] && update-desktop-database "$DESKTOP_FILE_LOCATION" && update-desktop-database "$DATA_HOME/icons"
print "${COLOR_GREEN}OK${COLOR_RESET}"
# On some systems this directory doesn't exist by default
mkdir -p "$DESKTOP_FILE_LOCATION"
# No spaces or tabs should be used for indentation with Bash heredocs
cat >> "$DESKTOP_FILE_LOCATION/appimagekit-joplin.desktop" <<-EOF
[Desktop Entry]
Encoding=UTF-8
Name=Joplin
Comment=Joplin for Desktop
Exec=${HOME}/.joplin/Joplin.AppImage ${SANDBOXPARAM} %u
Icon=joplin
StartupWMClass=Joplin
Type=Application
Categories=Office;
MimeType=x-scheme-handler/joplin;
X-GNOME-SingleWindow=true // should be removed eventually as it was upstream to be an XDG specification
SingleMainWindow=true
EOF
# Update application icons
[[ `command -v update-desktop-database` ]] && update-desktop-database "$DESKTOP_FILE_LOCATION" && update-desktop-database "$DATA_HOME/icons"
print "${COLOR_GREEN}OK${COLOR_RESET}"
else
print "${COLOR_RED}NOT DONE, unknown desktop '${DESKTOP}'${COLOR_RESET}"
print "${COLOR_RED}NOT DONE, unknown desktop '${DESKTOP}'${COLOR_RESET}"
fi
#-----------------------------------------------------
@@ -271,8 +270,8 @@ echo "$RELEASE_VERSION" > ~/.joplin/VERSION
#-----------------------------------------------------
if [[ "$SHOW_CHANGELOG" == true ]]; then
NOTES=$(wget -qO - https://api.github.com/repos/laurent22/joplin/releases/latest | grep -Po '"body": "\K.*(?=")')
print "${COLOR_BLUE}Changelog:${COLOR_RESET}\n${NOTES}"
NOTES=$(wget -qO - https://api.github.com/repos/laurent22/joplin/releases/latest | grep -Po '"body": "\K.*(?=")')
print "${COLOR_BLUE}Changelog:${COLOR_RESET}\n${NOTES}"
fi
#-----------------------------------------------------

View File

@@ -31,7 +31,7 @@ Please see the [donation page](https://github.com/laurent22/joplin/blob/dev/read
# Sponsors
<!-- SPONSORS-ORG -->
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&amp;mtm_kwd=joplinapp&amp;mtm_source=joplinapp-webseite&amp;mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a> <a href="https://tranio.com/spain/"><img title="Property for sale in Spain" width="256" src="https://joplinapp.org/images/sponsors/TranioOverseasProperty.jpg"/></a> <a href="https://citricsheep.com"><img title="Citric Sheep" width="256" src="https://joplinapp.org/images/sponsors/CitricSheep.png"/></a>
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&amp;mtm_kwd=joplinapp&amp;mtm_source=joplinapp-webseite&amp;mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a> <a href="https://citricsheep.com"><img title="Citric Sheep" width="256" src="https://joplinapp.org/images/sponsors/CitricSheep.png"/></a> <a href="https://sorted.travel/?utm_source=joplinapp "><img title="Sorted Travel" width="256" src="https://joplinapp.org/images/sponsors/SortedTravel.png"/></a> <a href="https://celebian.com "><img title="Celebian" width="256" src="https://joplinapp.org/images/sponsors/Celebian.png"/></a>
<!-- SPONSORS-ORG -->
* * *

View File

@@ -1,5 +1,5 @@
# For development this compose file starts the database only. The app can then
# be started using `yarn run start-dev`, which is useful for development, because
# be started using `yarn start-dev`, which is useful for development, because
# it means the app Docker file doesn't have to be rebuilt on each change.
version: '3'

16
jest.base-setup.js Normal file
View File

@@ -0,0 +1,16 @@
/* eslint-disable jest/require-top-level-describe */
module.exports = () => {
// Disable the additional information that Jest adds to each console
// statement. It's rarely needed and if it is it can be commented out here.
const jestConsole = console;
beforeEach(() => {
global.console = require('console');
});
afterEach(() => {
global.console = jestConsole;
});
};

View File

@@ -11,9 +11,9 @@ module.exports = {
//
// '**/*.ts?(x)': () => 'npm run tsc',
'*.{js,jsx,ts,tsx}': [
'yarn run checkIgnoredFiles',
// 'yarn run checkLibPaths',
'yarn run packageJsonLint',
'yarn run linter-precommit',
'yarn checkIgnoredFiles',
// 'yarn checkLibPaths',
'yarn packageJsonLint',
'yarn linter-precommit',
],
};

View File

@@ -13,14 +13,14 @@
},
"scripts": {
"buildApiDoc": "yarn workspace joplin start apidoc ../../readme/api/references/rest_api.md",
"buildCommandIndex": "node packages/tools/gulp/tasks/buildCommandIndexRun.js",
"buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn run tsc",
"buildPluginDoc": "cd packages/generate-plugin-doc && yarn run buildPluginDoc_",
"buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc",
"buildScriptIndexes": "node packages/tools/gulp/tasks/buildScriptIndexesRun.js",
"buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn tsc",
"buildPluginDoc": "cd packages/generate-plugin-doc && yarn buildPluginDoc_",
"buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn tsc",
"buildServerDocker": "node packages/tools/buildServerDocker.js",
"buildSettingJsonSchema": "yarn workspace joplin start settingschema ../../../joplin-website/docs/schema/settings.json",
"buildTranslations": "node packages/tools/build-translation.js",
"buildWebsite": "node ./packages/tools/website/processDocs.js --env prod && node ./packages/tools/website/build.js && yarn run buildPluginDoc && yarn run buildSettingJsonSchema",
"buildWebsite": "node ./packages/tools/website/processDocs.js --env prod && node ./packages/tools/website/build.js && yarn buildPluginDoc && yarn buildSettingJsonSchema",
"buildWebsiteTranslations": "node packages/tools/website/buildTranslations.js",
"checkIgnoredFiles": "node ./packages/tools/checkIgnoredFiles.js",
"checkLibPaths": "node ./packages/tools/checkLibPaths.js",
@@ -31,7 +31,7 @@
"crowdinUpload": "crowdin upload",
"cspell": "cspell",
"dependencyTree": "madge",
"generateDatabaseTypes": "node packages/tools/generate-database-types",
"generateTypes": "node packages/tools/generate-database-types",
"linkChecker": "linkchecker https://joplinapp.org/ && linkchecker --check-extern https://joplinapp.org/api/references/plugin_api/classes/joplin.html",
"linter-ci": "eslint --resolve-plugins-relative-to . --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
"linter-interactive": "eslint-interactive --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
@@ -40,7 +40,7 @@
"packageJsonLint": "node ./packages/tools/packageJsonLint.js",
"postinstall": "gulp build",
"postPreReleasesToForum": "node ./packages/tools/postPreReleasesToForum",
"publishAll": "git pull && yarn run buildParallel && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
"publishAll": "git pull && yarn buildParallel && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
"releaseAndroid": "PATH=\"/usr/local/opt/openjdk@11/bin:$PATH\" node packages/tools/release-android.js",
"releaseAndroidClean": "node packages/tools/release-android.js",
"releaseCli": "node packages/tools/release-cli.js",
@@ -72,39 +72,42 @@
"@crowdin/cli": "3",
"@joplin/utils": "~2.12",
"@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0",
"@typescript-eslint/eslint-plugin": "6.7.2",
"@typescript-eslint/parser": "6.7.2",
"@typescript-eslint/eslint-plugin": "6.8.0",
"@typescript-eslint/parser": "6.8.0",
"cspell": "5.21.2",
"eslint": "8.49.0",
"eslint": "8.52.0",
"eslint-interactive": "10.8.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jest": "27.4.0",
"eslint-plugin-jest": "27.4.3",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.33.2",
"execa": "5.1.1",
"fs-extra": "11.1.1",
"fs-extra": "11.2.0",
"glob": "10.3.10",
"gulp": "4.0.2",
"husky": "3.1.0",
"lerna": "3.22.1",
"lint-staged": "14.0.1",
"lint-staged": "15.2.0",
"madge": "6.1.0",
"npm-package-json-lint": "7.0.0",
"npm-package-json-lint": "7.1.0",
"typescript": "5.2.2"
},
"dependencies": {
"@types/fs-extra": "11.0.3",
"eslint-plugin-github": "4.10.0",
"@types/fs-extra": "11.0.4",
"eslint-plugin-github": "4.10.1",
"http-server": "14.1.1",
"node-gyp": "9.4.1",
"nodemon": "3.0.1"
"nodemon": "3.0.3"
},
"packageManager": "yarn@3.6.4",
"resolutions": {
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
"react-native-vosk@0.1.12": "patch:react-native-vosk@npm%3A0.1.12#./.yarn/patches/react-native-vosk-npm-0.1.12-76b1caaae8.patch",
"eslint": "patch:eslint@8.49.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
"eslint": "patch:eslint@8.52.0#./.yarn/patches/eslint-npm-8.39.0-d92bace04d.patch",
"app-builder-lib@24.4.0": "patch:app-builder-lib@npm%3A24.4.0#./.yarn/patches/app-builder-lib-npm-24.4.0-05322ff057.patch",
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch"
"react-native@0.71.10": "patch:react-native@npm%3A0.71.10#./.yarn/patches/react-native-animation-fix/react-native-npm-0.71.10-f9c32562d8.patch",
"nanoid": "patch:nanoid@npm%3A3.3.7#./.yarn/patches/nanoid-npm-3.3.7-98824ba130.patch",
"pdfjs-dist": "patch:pdfjs-dist@npm%3A3.11.174#./.yarn/patches/pdfjs-dist-npm-3.11.174-67f2fee6d6.patch",
"@react-native-community/slider": "patch:@react-native-community/slider@npm%3A4.4.4#./.yarn/patches/@react-native-community-slider-npm-4.4.4-d78e472f48.patch"
}
}

View File

@@ -1,469 +1,461 @@
const BaseApplication = require('@joplin/lib/BaseApplication').default;
const { FoldersScreenUtils } = require('@joplin/lib/folders-screen-utils.js');
const ResourceService = require('@joplin/lib/services/ResourceService').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const Folder = require('@joplin/lib/models/Folder').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
const Setting = require('@joplin/lib/models/Setting').default;
const { reg } = require('@joplin/lib/registry.js');
const { fileExtension } = require('@joplin/lib/path-utils');
const { splitCommandString } = require('@joplin/utils');
const { splitCommandBatch } = require('@joplin/lib/string-utils');
const { _ } = require('@joplin/lib/locale');
const fs = require('fs-extra');
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const BaseApplication_1 = require("@joplin/lib/BaseApplication");
const folders_screen_utils_js_1 = require("@joplin/lib/folders-screen-utils.js");
const ResourceService_1 = require("@joplin/lib/services/ResourceService");
const BaseModel_1 = require("@joplin/lib/BaseModel");
const Folder_1 = require("@joplin/lib/models/Folder");
const BaseItem_1 = require("@joplin/lib/models/BaseItem");
const Note_1 = require("@joplin/lib/models/Note");
const Tag_1 = require("@joplin/lib/models/Tag");
const Setting_1 = require("@joplin/lib/models/Setting");
const registry_js_1 = require("@joplin/lib/registry.js");
const path_utils_1 = require("@joplin/lib/path-utils");
const utils_1 = require("@joplin/utils");
const locale_1 = require("@joplin/lib/locale");
const fs_extra_1 = require("fs-extra");
const RevisionService_1 = require("@joplin/lib/services/RevisionService");
const shim_1 = require("@joplin/lib/shim");
const setupCommand_1 = require("./setupCommand");
const { cliUtils } = require('./cli-utils.js');
const Cache = require('@joplin/lib/Cache');
const RevisionService = require('@joplin/lib/services/RevisionService').default;
const shim = require('@joplin/lib/shim').default;
const setupCommand = require('./setupCommand').default;
class Application extends BaseApplication {
constructor() {
super();
this.showPromptString_ = true;
this.commands_ = {};
this.commandMetadata_ = null;
this.activeCommand_ = null;
this.allCommandsLoaded_ = false;
this.showStackTraces_ = false;
this.gui_ = null;
this.cache_ = new Cache();
}
gui() {
return this.gui_;
}
commandStdoutMaxWidth() {
return this.gui().stdoutMaxWidth();
}
async guessTypeAndLoadItem(pattern, options = null) {
let type = BaseModel.TYPE_NOTE;
if (pattern.indexOf('/') === 0) {
type = BaseModel.TYPE_FOLDER;
pattern = pattern.substr(1);
}
return this.loadItem(type, pattern, options);
}
async loadItem(type, pattern, options = null) {
const output = await this.loadItems(type, pattern, options);
if (output.length > 1) {
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
// let answers = { 0: _('[Cancel]') };
// for (let i = 0; i < output.length; i++) {
// answers[i + 1] = output[i].title;
// }
// Not really useful with new UI?
throw new Error(_('More than one item match "%s". Please narrow down your query.', pattern));
// let msg = _('More than one item match "%s". Please select one:', pattern);
// const response = await cliUtils.promptMcq(msg, answers);
// if (!response) return null;
// return output[response - 1];
} else {
return output.length ? output[0] : null;
}
}
async loadItems(type, pattern, options = null) {
if (type === 'folderOrNote') {
const folders = await this.loadItems(BaseModel.TYPE_FOLDER, pattern, options);
if (folders.length) return folders;
return await this.loadItems(BaseModel.TYPE_NOTE, pattern, options);
}
pattern = pattern ? pattern.toString() : '';
if (type === BaseModel.TYPE_FOLDER && (pattern === Folder.conflictFolderTitle() || pattern === Folder.conflictFolderId())) return [Folder.conflictFolder()];
if (!options) options = {};
const parent = options.parent ? options.parent : app().currentFolder();
const ItemClass = BaseItem.itemClass(type);
if (type === BaseModel.TYPE_NOTE && pattern.indexOf('*') >= 0) {
// Handle it as pattern
if (!parent) throw new Error(_('No notebook selected.'));
return await Note.previews(parent.id, { titlePattern: pattern });
} else {
// Single item
let item = null;
if (type === BaseModel.TYPE_NOTE) {
if (!parent) throw new Error(_('No notebook has been specified.'));
item = await ItemClass.loadFolderNoteByField(parent.id, 'title', pattern);
} else {
item = await ItemClass.loadByTitle(pattern);
}
if (item) return [item];
item = await ItemClass.load(pattern); // Load by id
if (item) return [item];
if (pattern.length >= 2) {
return await ItemClass.loadByPartialId(pattern);
}
}
return [];
}
setupCommand(cmd) {
return setupCommand(cmd, t => this.stdout(t), () => this.store(), () => this.gui());
}
stdout(text) {
return this.gui().stdout(text);
}
async exit(code = 0) {
const doExit = async () => {
this.gui().exit();
await super.exit(code);
};
// Give it a few seconds to cancel otherwise exit anyway
shim.setTimeout(async () => {
await doExit();
}, 5000);
if (await reg.syncTarget().syncStarted()) {
this.stdout(_('Cancelling background synchronisation... Please wait.'));
const sync = await reg.syncTarget().synchronizer();
await sync.cancel();
}
await doExit();
}
commands(uiType = null) {
if (!this.allCommandsLoaded_) {
// eslint-disable-next-line github/array-foreach -- Old code before rule was applied
fs.readdirSync(__dirname).forEach(path => {
if (path.indexOf('command-') !== 0) return;
if (path.endsWith('.test.js')) return;
const ext = fileExtension(path);
if (ext !== 'js') return;
const CommandClass = require(`./${path}`);
let cmd = new CommandClass();
if (!cmd.enabled()) return;
cmd = this.setupCommand(cmd);
this.commands_[cmd.name()] = cmd;
});
this.allCommandsLoaded_ = true;
}
if (uiType !== null) {
const temp = [];
for (const n in this.commands_) {
if (!this.commands_.hasOwnProperty(n)) continue;
const c = this.commands_[n];
if (!c.supportsUi(uiType)) continue;
temp[n] = c;
}
return temp;
}
return this.commands_;
}
async commandNames() {
const metadata = await this.commandMetadata();
const output = [];
for (const n in metadata) {
if (!metadata.hasOwnProperty(n)) continue;
output.push(n);
}
return output;
}
async commandMetadata() {
if (this.commandMetadata_) return this.commandMetadata_;
let output = await this.cache_.getItem('metadata');
if (output) {
this.commandMetadata_ = output;
return { ...this.commandMetadata_ };
}
const commands = this.commands();
output = {};
for (const n in commands) {
if (!commands.hasOwnProperty(n)) continue;
const cmd = commands[n];
output[n] = cmd.metadata();
}
await this.cache_.setItem('metadata', output, 1000 * 60 * 60 * 24);
this.commandMetadata_ = output;
return { ...this.commandMetadata_ };
}
hasGui() {
return this.gui() && !this.gui().isDummy();
}
findCommandByName(name) {
if (this.commands_[name]) return this.commands_[name];
let CommandClass = null;
try {
CommandClass = require(`${__dirname}/command-${name}.js`);
} catch (error) {
if (error.message && error.message.indexOf('Cannot find module') >= 0) {
const e = new Error(_('No such command: %s', name));
e.type = 'notFound';
throw e;
} else {
throw error;
}
}
let cmd = new CommandClass();
cmd = this.setupCommand(cmd);
this.commands_[name] = cmd;
return this.commands_[name];
}
dummyGui() {
return {
isDummy: () => {
return true;
},
prompt: (initialText = '', promptString = '', options = null) => {
return cliUtils.prompt(initialText, promptString, options);
},
showConsole: () => {},
maximizeConsole: () => {},
stdout: text => {
// eslint-disable-next-line no-console
console.info(text);
},
fullScreen: () => {},
exit: () => {},
showModalOverlay: () => {},
hideModalOverlay: () => {},
stdoutMaxWidth: () => {
return 100;
},
forceRender: () => {},
termSaveState: () => {},
termRestoreState: () => {},
};
}
async execCommand(argv) {
if (!argv.length) return this.execCommand(['help']);
// reg.logger().debug('execCommand()', argv);
const commandName = argv[0];
this.activeCommand_ = this.findCommandByName(commandName);
let outException = null;
try {
if (this.gui().isDummy() && !this.activeCommand_.supportsUi('cli')) throw new Error(_('The command "%s" is only available in GUI mode', this.activeCommand_.name()));
const cmdArgs = cliUtils.makeCommandArgs(this.activeCommand_, argv);
await this.activeCommand_.action(cmdArgs);
} catch (error) {
outException = error;
}
this.activeCommand_ = null;
if (outException) throw outException;
}
currentCommand() {
return this.activeCommand_;
}
async loadKeymaps() {
const defaultKeyMap = [
{ keys: [':'], type: 'function', command: 'enter_command_line_mode' },
{ keys: ['TAB'], type: 'function', command: 'focus_next' },
{ keys: ['SHIFT_TAB'], type: 'function', command: 'focus_previous' },
{ keys: ['UP'], type: 'function', command: 'move_up' },
{ keys: ['DOWN'], type: 'function', command: 'move_down' },
{ keys: ['PAGE_UP'], type: 'function', command: 'page_up' },
{ keys: ['PAGE_DOWN'], type: 'function', command: 'page_down' },
{ keys: ['ENTER'], type: 'function', command: 'activate' },
{ keys: ['DELETE', 'BACKSPACE'], type: 'function', command: 'delete' },
{ keys: ['n'], type: 'function', command: 'next_link' },
{ keys: ['b'], type: 'function', command: 'previous_link' },
{ keys: ['o'], type: 'function', command: 'open_link' },
{ keys: [' '], command: 'todo toggle $n' },
{ keys: ['tc'], type: 'function', command: 'toggle_console' },
{ keys: ['tm'], type: 'function', command: 'toggle_metadata' },
{ keys: ['ti'], type: 'function', command: 'toggle_ids' },
{ keys: ['/'], type: 'prompt', command: 'search ""', cursorPosition: -2 },
{ keys: ['mn'], type: 'prompt', command: 'mknote ""', cursorPosition: -2 },
{ keys: ['mt'], type: 'prompt', command: 'mktodo ""', cursorPosition: -2 },
{ keys: ['mb'], type: 'prompt', command: 'mkbook ""', cursorPosition: -2 },
{ keys: ['yn'], type: 'prompt', command: 'cp $n ""', cursorPosition: -2 },
{ keys: ['dn'], type: 'prompt', command: 'mv $n ""', cursorPosition: -2 },
];
// Filter the keymap item by command so that items in keymap.json can override
// the default ones.
const itemsByCommand = {};
for (let i = 0; i < defaultKeyMap.length; i++) {
itemsByCommand[defaultKeyMap[i].command] = defaultKeyMap[i];
}
const filePath = `${Setting.value('profileDir')}/keymap.json`;
if (await fs.pathExists(filePath)) {
try {
let configString = await fs.readFile(filePath, 'utf-8');
configString = configString.replace(/^\s*\/\/.*/, ''); // Strip off comments
const keymap = JSON.parse(configString);
for (let keymapIndex = 0; keymapIndex < keymap.length; keymapIndex++) {
const item = keymap[keymapIndex];
itemsByCommand[item.command] = item;
}
} catch (error) {
let msg = error.message ? error.message : '';
msg = `Could not load keymap ${filePath}\n${msg}`;
error.message = msg;
throw error;
}
}
const output = [];
for (const n in itemsByCommand) {
if (!itemsByCommand.hasOwnProperty(n)) continue;
output.push(itemsByCommand[n]);
}
// Map reserved shortcuts to their equivalent key
// https://github.com/cronvel/terminal-kit/issues/101
for (let i = 0; i < output.length; i++) {
const newKeys = output[i].keys.map(k => {
k = k.replace(/CTRL_H/g, 'BACKSPACE');
k = k.replace(/CTRL_I/g, 'TAB');
k = k.replace(/CTRL_M/g, 'ENTER');
return k;
});
output[i].keys = newKeys;
}
return output;
}
async commandList(argv) {
if (argv.length && argv[0] === 'batch') {
const commands = [];
const commandLines = splitCommandBatch(await fs.readFile(argv[1], 'utf-8'));
for (const commandLine of commandLines) {
if (!commandLine.trim()) continue;
const splitted = splitCommandString(commandLine.trim());
commands.push(splitted);
}
return commands;
} else {
return [argv];
}
}
// We need this special case here because by the time the `version` command
// runs, the keychain has already been setup.
checkIfKeychainEnabled(argv) {
return argv.indexOf('version') < 0;
}
async start(argv) {
const keychainEnabled = this.checkIfKeychainEnabled(argv);
argv = await super.start(argv, { keychainEnabled });
cliUtils.setStdout(object => {
return this.stdout(object);
});
this.initRedux();
// If we have some arguments left at this point, it's a command
// so execute it.
if (argv.length) {
this.gui_ = this.dummyGui();
this.currentFolder_ = await Folder.load(Setting.value('activeFolderId'));
await this.applySettingsSideEffects();
try {
const commands = await this.commandList(argv);
for (const command of commands) {
await this.execCommand(command);
}
} catch (error) {
if (this.showStackTraces_) {
console.error(error);
} else {
// eslint-disable-next-line no-console
console.info(error.message);
}
process.exit(1);
}
await Setting.saveAll();
// Need to call exit() explicitly, otherwise Node wait for any timeout to complete
// https://stackoverflow.com/questions/18050095
process.exit(0);
} else {
// Otherwise open the GUI
const keymap = await this.loadKeymaps();
const AppGui = require('./app-gui.js');
this.gui_ = new AppGui(this, this.store(), keymap);
this.gui_.setLogger(this.logger());
await this.gui_.start();
// Since the settings need to be loaded before the store is created, it will never
// receive the SETTING_UPDATE_ALL even, which mean state.settings will not be
// initialised. So we manually call dispatchUpdateAll() to force an update.
Setting.dispatchUpdateAll();
await FoldersScreenUtils.refreshFolders();
const tags = await Tag.allWithNotes();
ResourceService.runInBackground();
RevisionService.instance().runInBackground();
this.dispatch({
type: 'TAG_UPDATE_ALL',
items: tags,
});
this.store().dispatch({
type: 'FOLDER_SELECT',
id: Setting.value('activeFolderId'),
});
this.startRotatingLogMaintenance(Setting.value('profileDir'));
}
}
const { splitCommandBatch } = require('@joplin/lib/string-utils');
class Application extends BaseApplication_1.default {
constructor() {
super(...arguments);
this.commands_ = {};
this.commandMetadata_ = null;
this.activeCommand_ = null;
this.allCommandsLoaded_ = false;
this.gui_ = null;
this.cache_ = new Cache();
}
gui() {
return this.gui_;
}
commandStdoutMaxWidth() {
return this.gui().stdoutMaxWidth();
}
guessTypeAndLoadItem(pattern, options = null) {
return __awaiter(this, void 0, void 0, function* () {
let type = BaseModel_1.default.TYPE_NOTE;
if (pattern.indexOf('/') === 0) {
type = BaseModel_1.default.TYPE_FOLDER;
pattern = pattern.substr(1);
}
return this.loadItem(type, pattern, options);
});
}
loadItem(type, pattern, options = null) {
return __awaiter(this, void 0, void 0, function* () {
const output = yield this.loadItems(type, pattern, options);
if (output.length > 1) {
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
// let answers = { 0: _('[Cancel]') };
// for (let i = 0; i < output.length; i++) {
// answers[i + 1] = output[i].title;
// }
// Not really useful with new UI?
throw new Error((0, locale_1._)('More than one item match "%s". Please narrow down your query.', pattern));
// let msg = _('More than one item match "%s". Please select one:', pattern);
// const response = await cliUtils.promptMcq(msg, answers);
// if (!response) return null;
// return output[response - 1];
}
else {
return output.length ? output[0] : null;
}
});
}
loadItems(type, pattern, options = null) {
return __awaiter(this, void 0, void 0, function* () {
if (type === 'folderOrNote') {
const folders = yield this.loadItems(BaseModel_1.default.TYPE_FOLDER, pattern, options);
if (folders.length)
return folders;
return yield this.loadItems(BaseModel_1.default.TYPE_NOTE, pattern, options);
}
pattern = pattern ? pattern.toString() : '';
if (type === BaseModel_1.default.TYPE_FOLDER && (pattern === Folder_1.default.conflictFolderTitle() || pattern === Folder_1.default.conflictFolderId()))
return [Folder_1.default.conflictFolder()];
if (!options)
options = {};
const parent = options.parent ? options.parent : app().currentFolder();
const ItemClass = BaseItem_1.default.itemClass(type);
if (type === BaseModel_1.default.TYPE_NOTE && pattern.indexOf('*') >= 0) {
// Handle it as pattern
if (!parent)
throw new Error((0, locale_1._)('No notebook selected.'));
return yield Note_1.default.previews(parent.id, { titlePattern: pattern });
}
else {
// Single item
let item = null;
if (type === BaseModel_1.default.TYPE_NOTE) {
if (!parent)
throw new Error((0, locale_1._)('No notebook has been specified.'));
item = yield ItemClass.loadFolderNoteByField(parent.id, 'title', pattern);
}
else {
item = yield ItemClass.loadByTitle(pattern);
}
if (item)
return [item];
item = yield ItemClass.load(pattern); // Load by id
if (item)
return [item];
if (pattern.length >= 2) {
return yield ItemClass.loadByPartialId(pattern);
}
}
return [];
});
}
setupCommand(cmd) {
return (0, setupCommand_1.default)(cmd, (t) => this.stdout(t), () => this.store(), () => this.gui());
}
stdout(text) {
return this.gui().stdout(text);
}
exit(code = 0) {
const _super = Object.create(null, {
exit: { get: () => super.exit }
});
return __awaiter(this, void 0, void 0, function* () {
const doExit = () => __awaiter(this, void 0, void 0, function* () {
this.gui().exit();
yield _super.exit.call(this, code);
});
// Give it a few seconds to cancel otherwise exit anyway
shim_1.default.setTimeout(() => __awaiter(this, void 0, void 0, function* () {
yield doExit();
}), 5000);
if (yield registry_js_1.reg.syncTarget().syncStarted()) {
this.stdout((0, locale_1._)('Cancelling background synchronisation... Please wait.'));
const sync = yield registry_js_1.reg.syncTarget().synchronizer();
yield sync.cancel();
}
yield doExit();
});
}
commands(uiType = null) {
if (!this.allCommandsLoaded_) {
// eslint-disable-next-line github/array-foreach -- Old code before rule was applied
(0, fs_extra_1.readdirSync)(__dirname).forEach(path => {
if (path.indexOf('command-') !== 0)
return;
if (path.endsWith('.test.js'))
return;
const ext = (0, path_utils_1.fileExtension)(path);
if (ext !== 'js')
return;
const CommandClass = require(`./${path}`);
let cmd = new CommandClass();
if (!cmd.enabled())
return;
cmd = this.setupCommand(cmd);
this.commands_[cmd.name()] = cmd;
});
this.allCommandsLoaded_ = true;
}
if (uiType !== null) {
const temp = {};
for (const n in this.commands_) {
if (!this.commands_.hasOwnProperty(n))
continue;
const c = this.commands_[n];
if (!c.supportsUi(uiType))
continue;
temp[n] = c;
}
return temp;
}
return this.commands_;
}
commandNames() {
return __awaiter(this, void 0, void 0, function* () {
const metadata = yield this.commandMetadata();
const output = [];
for (const n in metadata) {
if (!metadata.hasOwnProperty(n))
continue;
output.push(n);
}
return output;
});
}
commandMetadata() {
return __awaiter(this, void 0, void 0, function* () {
if (this.commandMetadata_)
return this.commandMetadata_;
let output = yield this.cache_.getItem('metadata');
if (output) {
this.commandMetadata_ = output;
return Object.assign({}, this.commandMetadata_);
}
const commands = this.commands();
output = {};
for (const n in commands) {
if (!commands.hasOwnProperty(n))
continue;
const cmd = commands[n];
output[n] = cmd.metadata();
}
yield this.cache_.setItem('metadata', output, 1000 * 60 * 60 * 24);
this.commandMetadata_ = output;
return Object.assign({}, this.commandMetadata_);
});
}
hasGui() {
return this.gui() && !this.gui().isDummy();
}
findCommandByName(name) {
if (this.commands_[name])
return this.commands_[name];
let CommandClass = null;
try {
CommandClass = require(`${__dirname}/command-${name}.js`);
}
catch (error) {
if (error.message && error.message.indexOf('Cannot find module') >= 0) {
const e = new Error((0, locale_1._)('No such command: %s', name));
e.type = 'notFound';
throw e;
}
else {
throw error;
}
}
let cmd = new CommandClass();
cmd = this.setupCommand(cmd);
this.commands_[name] = cmd;
return this.commands_[name];
}
dummyGui() {
return {
isDummy: () => {
return true;
},
prompt: (initialText = '', promptString = '', options = null) => {
return cliUtils.prompt(initialText, promptString, options);
},
showConsole: () => { },
maximizeConsole: () => { },
stdout: (text) => {
// eslint-disable-next-line no-console
console.info(text);
},
fullScreen: () => { },
exit: () => { },
showModalOverlay: () => { },
hideModalOverlay: () => { },
stdoutMaxWidth: () => {
return 100;
},
forceRender: () => { },
termSaveState: () => { },
termRestoreState: () => { },
};
}
execCommand(argv) {
return __awaiter(this, void 0, void 0, function* () {
if (!argv.length)
return this.execCommand(['help']);
// reg.logger().debug('execCommand()', argv);
const commandName = argv[0];
this.activeCommand_ = this.findCommandByName(commandName);
let outException = null;
try {
if (this.gui().isDummy() && !this.activeCommand_.supportsUi('cli'))
throw new Error((0, locale_1._)('The command "%s" is only available in GUI mode', this.activeCommand_.name()));
const cmdArgs = cliUtils.makeCommandArgs(this.activeCommand_, argv);
yield this.activeCommand_.action(cmdArgs);
}
catch (error) {
outException = error;
}
this.activeCommand_ = null;
if (outException)
throw outException;
});
}
currentCommand() {
return this.activeCommand_;
}
loadKeymaps() {
return __awaiter(this, void 0, void 0, function* () {
const defaultKeyMap = [
{ keys: [':'], type: 'function', command: 'enter_command_line_mode' },
{ keys: ['TAB'], type: 'function', command: 'focus_next' },
{ keys: ['SHIFT_TAB'], type: 'function', command: 'focus_previous' },
{ keys: ['UP'], type: 'function', command: 'move_up' },
{ keys: ['DOWN'], type: 'function', command: 'move_down' },
{ keys: ['PAGE_UP'], type: 'function', command: 'page_up' },
{ keys: ['PAGE_DOWN'], type: 'function', command: 'page_down' },
{ keys: ['ENTER'], type: 'function', command: 'activate' },
{ keys: ['DELETE', 'BACKSPACE'], type: 'function', command: 'delete' },
{ keys: ['n'], type: 'function', command: 'next_link' },
{ keys: ['b'], type: 'function', command: 'previous_link' },
{ keys: ['o'], type: 'function', command: 'open_link' },
{ keys: [' '], type: 'prompt', command: 'todo toggle $n' },
{ keys: ['tc'], type: 'function', command: 'toggle_console' },
{ keys: ['tm'], type: 'function', command: 'toggle_metadata' },
{ keys: ['ti'], type: 'function', command: 'toggle_ids' },
{ keys: ['/'], type: 'prompt', command: 'search ""', cursorPosition: -2 },
{ keys: ['mn'], type: 'prompt', command: 'mknote ""', cursorPosition: -2 },
{ keys: ['mt'], type: 'prompt', command: 'mktodo ""', cursorPosition: -2 },
{ keys: ['mb'], type: 'prompt', command: 'mkbook ""', cursorPosition: -2 },
{ keys: ['yn'], type: 'prompt', command: 'cp $n ""', cursorPosition: -2 },
{ keys: ['dn'], type: 'prompt', command: 'mv $n ""', cursorPosition: -2 },
];
// Filter the keymap item by command so that items in keymap.json can override
// the default ones.
const itemsByCommand = {};
for (let i = 0; i < defaultKeyMap.length; i++) {
itemsByCommand[defaultKeyMap[i].command] = defaultKeyMap[i];
}
const filePath = `${Setting_1.default.value('profileDir')}/keymap.json`;
if (yield (0, fs_extra_1.pathExists)(filePath)) {
try {
let configString = yield (0, fs_extra_1.readFile)(filePath, 'utf-8');
configString = configString.replace(/^\s*\/\/.*/, ''); // Strip off comments
const keymap = JSON.parse(configString);
for (let keymapIndex = 0; keymapIndex < keymap.length; keymapIndex++) {
const item = keymap[keymapIndex];
itemsByCommand[item.command] = item;
}
}
catch (error) {
let msg = error.message ? error.message : '';
msg = `Could not load keymap ${filePath}\n${msg}`;
error.message = msg;
throw error;
}
}
const output = [];
for (const n in itemsByCommand) {
if (!itemsByCommand.hasOwnProperty(n))
continue;
output.push(itemsByCommand[n]);
}
// Map reserved shortcuts to their equivalent key
// https://github.com/cronvel/terminal-kit/issues/101
for (let i = 0; i < output.length; i++) {
const newKeys = output[i].keys.map(k => {
k = k.replace(/CTRL_H/g, 'BACKSPACE');
k = k.replace(/CTRL_I/g, 'TAB');
k = k.replace(/CTRL_M/g, 'ENTER');
return k;
});
output[i].keys = newKeys;
}
return output;
});
}
commandList(argv) {
return __awaiter(this, void 0, void 0, function* () {
if (argv.length && argv[0] === 'batch') {
const commands = [];
const commandLines = splitCommandBatch(yield (0, fs_extra_1.readFile)(argv[1], 'utf-8'));
for (const commandLine of commandLines) {
if (!commandLine.trim())
continue;
const splitted = (0, utils_1.splitCommandString)(commandLine.trim());
commands.push(splitted);
}
return commands;
}
else {
return [argv];
}
});
}
// We need this special case here because by the time the `version` command
// runs, the keychain has already been setup.
checkIfKeychainEnabled(argv) {
return argv.indexOf('version') < 0;
}
start(argv) {
const _super = Object.create(null, {
start: { get: () => super.start }
});
return __awaiter(this, void 0, void 0, function* () {
const keychainEnabled = this.checkIfKeychainEnabled(argv);
argv = yield _super.start.call(this, argv, { keychainEnabled });
cliUtils.setStdout((object) => {
return this.stdout(object);
});
this.initRedux();
// If we have some arguments left at this point, it's a command
// so execute it.
if (argv.length) {
this.gui_ = this.dummyGui();
this.currentFolder_ = yield Folder_1.default.load(Setting_1.default.value('activeFolderId'));
yield this.applySettingsSideEffects();
try {
const commands = yield this.commandList(argv);
for (const command of commands) {
yield this.execCommand(command);
}
}
catch (error) {
if (this.showStackTraces_) {
console.error(error);
}
else {
// eslint-disable-next-line no-console
console.info(error.message);
}
process.exit(1);
}
yield Setting_1.default.saveAll();
// Need to call exit() explicitly, otherwise Node wait for any timeout to complete
// https://stackoverflow.com/questions/18050095
process.exit(0);
}
else {
// Otherwise open the GUI
const keymap = yield this.loadKeymaps();
const AppGui = require('./app-gui.js');
this.gui_ = new AppGui(this, this.store(), keymap);
this.gui_.setLogger(this.logger());
yield this.gui_.start();
// Since the settings need to be loaded before the store is created, it will never
// receive the SETTING_UPDATE_ALL even, which mean state.settings will not be
// initialised. So we manually call dispatchUpdateAll() to force an update.
Setting_1.default.dispatchUpdateAll();
yield (0, folders_screen_utils_js_1.refreshFolders)((action) => this.store().dispatch(action));
const tags = yield Tag_1.default.allWithNotes();
ResourceService_1.default.runInBackground();
RevisionService_1.default.instance().runInBackground();
this.dispatch({
type: 'TAG_UPDATE_ALL',
items: tags,
});
this.store().dispatch({
type: 'FOLDER_SELECT',
id: Setting_1.default.value('activeFolderId'),
});
this.startRotatingLogMaintenance(Setting_1.default.value('profileDir'));
}
});
}
}
let application_ = null;
function app() {
if (application_) return application_;
application_ = new Application();
return application_;
if (application_)
return application_;
application_ = new Application();
return application_;
}
module.exports = { app };
exports.default = app;
//# sourceMappingURL=app.js.map

472
packages/app-cli/app/app.ts Normal file
View File

@@ -0,0 +1,472 @@
import BaseApplication from '@joplin/lib/BaseApplication';
import { refreshFolders } from '@joplin/lib/folders-screen-utils.js';
import ResourceService from '@joplin/lib/services/ResourceService';
import BaseModel, { ModelType } from '@joplin/lib/BaseModel';
import Folder from '@joplin/lib/models/Folder';
import BaseItem from '@joplin/lib/models/BaseItem';
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
import Setting from '@joplin/lib/models/Setting';
import { reg } from '@joplin/lib/registry.js';
import { fileExtension } from '@joplin/lib/path-utils';
import { splitCommandString } from '@joplin/utils';
import { _ } from '@joplin/lib/locale';
import { pathExists, readFile, readdirSync } from 'fs-extra';
import RevisionService from '@joplin/lib/services/RevisionService';
import shim from '@joplin/lib/shim';
import setupCommand from './setupCommand';
import { FolderEntity, NoteEntity } from '@joplin/lib/services/database/types';
const { cliUtils } = require('./cli-utils.js');
const Cache = require('@joplin/lib/Cache');
const { splitCommandBatch } = require('@joplin/lib/string-utils');
class Application extends BaseApplication {
private commands_: Record<string, any> = {};
private commandMetadata_: any = null;
private activeCommand_: any = null;
private allCommandsLoaded_ = false;
private gui_: any = null;
private cache_ = new Cache();
public gui() {
return this.gui_;
}
public commandStdoutMaxWidth() {
return this.gui().stdoutMaxWidth();
}
public async guessTypeAndLoadItem(pattern: string, options: any = null) {
let type = BaseModel.TYPE_NOTE;
if (pattern.indexOf('/') === 0) {
type = BaseModel.TYPE_FOLDER;
pattern = pattern.substr(1);
}
return this.loadItem(type, pattern, options);
}
public async loadItem(type: ModelType | 'folderOrNote', pattern: string, options: any = null) {
const output = await this.loadItems(type, pattern, options);
if (output.length > 1) {
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
// let answers = { 0: _('[Cancel]') };
// for (let i = 0; i < output.length; i++) {
// answers[i + 1] = output[i].title;
// }
// Not really useful with new UI?
throw new Error(_('More than one item match "%s". Please narrow down your query.', pattern));
// let msg = _('More than one item match "%s". Please select one:', pattern);
// const response = await cliUtils.promptMcq(msg, answers);
// if (!response) return null;
// return output[response - 1];
} else {
return output.length ? output[0] : null;
}
}
public async loadItems(type: ModelType | 'folderOrNote', pattern: string, options: any = null): Promise<(FolderEntity | NoteEntity)[]> {
if (type === 'folderOrNote') {
const folders: FolderEntity[] = await this.loadItems(BaseModel.TYPE_FOLDER, pattern, options);
if (folders.length) return folders;
return await this.loadItems(BaseModel.TYPE_NOTE, pattern, options);
}
pattern = pattern ? pattern.toString() : '';
if (type === BaseModel.TYPE_FOLDER && (pattern === Folder.conflictFolderTitle() || pattern === Folder.conflictFolderId())) return [Folder.conflictFolder()];
if (!options) options = {};
const parent = options.parent ? options.parent : app().currentFolder();
const ItemClass = BaseItem.itemClass(type);
if (type === BaseModel.TYPE_NOTE && pattern.indexOf('*') >= 0) {
// Handle it as pattern
if (!parent) throw new Error(_('No notebook selected.'));
return await Note.previews(parent.id, { titlePattern: pattern });
} else {
// Single item
let item = null;
if (type === BaseModel.TYPE_NOTE) {
if (!parent) throw new Error(_('No notebook has been specified.'));
item = await ItemClass.loadFolderNoteByField(parent.id, 'title', pattern);
} else {
item = await ItemClass.loadByTitle(pattern);
}
if (item) return [item];
item = await ItemClass.load(pattern); // Load by id
if (item) return [item];
if (pattern.length >= 2) {
return await ItemClass.loadByPartialId(pattern);
}
}
return [];
}
public setupCommand(cmd: string) {
return setupCommand(cmd, (t: string) => this.stdout(t), () => this.store(), () => this.gui());
}
public stdout(text: string) {
return this.gui().stdout(text);
}
public async exit(code = 0) {
const doExit = async () => {
this.gui().exit();
await super.exit(code);
};
// Give it a few seconds to cancel otherwise exit anyway
shim.setTimeout(async () => {
await doExit();
}, 5000);
if (await reg.syncTarget().syncStarted()) {
this.stdout(_('Cancelling background synchronisation... Please wait.'));
const sync = await reg.syncTarget().synchronizer();
await sync.cancel();
}
await doExit();
}
public commands(uiType: string = null) {
if (!this.allCommandsLoaded_) {
// eslint-disable-next-line github/array-foreach -- Old code before rule was applied
readdirSync(__dirname).forEach(path => {
if (path.indexOf('command-') !== 0) return;
if (path.endsWith('.test.js')) return;
const ext = fileExtension(path);
if (ext !== 'js') return;
const CommandClass = require(`./${path}`);
let cmd = new CommandClass();
if (!cmd.enabled()) return;
cmd = this.setupCommand(cmd);
this.commands_[cmd.name()] = cmd;
});
this.allCommandsLoaded_ = true;
}
if (uiType !== null) {
const temp: Record<string, any> = {};
for (const n in this.commands_) {
if (!this.commands_.hasOwnProperty(n)) continue;
const c = this.commands_[n];
if (!c.supportsUi(uiType)) continue;
temp[n] = c;
}
return temp;
}
return this.commands_;
}
public async commandNames() {
const metadata = await this.commandMetadata();
const output = [];
for (const n in metadata) {
if (!metadata.hasOwnProperty(n)) continue;
output.push(n);
}
return output;
}
public async commandMetadata() {
if (this.commandMetadata_) return this.commandMetadata_;
let output = await this.cache_.getItem('metadata');
if (output) {
this.commandMetadata_ = output;
return { ...this.commandMetadata_ };
}
const commands = this.commands();
output = {};
for (const n in commands) {
if (!commands.hasOwnProperty(n)) continue;
const cmd = commands[n];
output[n] = cmd.metadata();
}
await this.cache_.setItem('metadata', output, 1000 * 60 * 60 * 24);
this.commandMetadata_ = output;
return { ...this.commandMetadata_ };
}
public hasGui() {
return this.gui() && !this.gui().isDummy();
}
public findCommandByName(name: string) {
if (this.commands_[name]) return this.commands_[name];
let CommandClass = null;
try {
CommandClass = require(`${__dirname}/command-${name}.js`);
} catch (error) {
if (error.message && error.message.indexOf('Cannot find module') >= 0) {
const e: any = new Error(_('No such command: %s', name));
e.type = 'notFound';
throw e;
} else {
throw error;
}
}
let cmd = new CommandClass();
cmd = this.setupCommand(cmd);
this.commands_[name] = cmd;
return this.commands_[name];
}
public dummyGui() {
return {
isDummy: () => {
return true;
},
prompt: (initialText = '', promptString = '', options: any = null) => {
return cliUtils.prompt(initialText, promptString, options);
},
showConsole: () => {},
maximizeConsole: () => {},
stdout: (text: string) => {
// eslint-disable-next-line no-console
console.info(text);
},
fullScreen: () => {},
exit: () => {},
showModalOverlay: () => {},
hideModalOverlay: () => {},
stdoutMaxWidth: () => {
return 100;
},
forceRender: () => {},
termSaveState: () => {},
termRestoreState: () => {},
};
}
public async execCommand(argv: string[]): Promise<any> {
if (!argv.length) return this.execCommand(['help']);
// reg.logger().debug('execCommand()', argv);
const commandName = argv[0];
this.activeCommand_ = this.findCommandByName(commandName);
let outException = null;
try {
if (this.gui().isDummy() && !this.activeCommand_.supportsUi('cli')) throw new Error(_('The command "%s" is only available in GUI mode', this.activeCommand_.name()));
const cmdArgs = cliUtils.makeCommandArgs(this.activeCommand_, argv);
await this.activeCommand_.action(cmdArgs);
} catch (error) {
outException = error;
}
this.activeCommand_ = null;
if (outException) throw outException;
}
public currentCommand() {
return this.activeCommand_;
}
public async loadKeymaps() {
interface KeyMapItem {
keys: string[];
type: 'function' | 'prompt';
command: string;
cursorPosition?: number;
}
const defaultKeyMap: KeyMapItem[] = [
{ keys: [':'], type: 'function', command: 'enter_command_line_mode' },
{ keys: ['TAB'], type: 'function', command: 'focus_next' },
{ keys: ['SHIFT_TAB'], type: 'function', command: 'focus_previous' },
{ keys: ['UP'], type: 'function', command: 'move_up' },
{ keys: ['DOWN'], type: 'function', command: 'move_down' },
{ keys: ['PAGE_UP'], type: 'function', command: 'page_up' },
{ keys: ['PAGE_DOWN'], type: 'function', command: 'page_down' },
{ keys: ['ENTER'], type: 'function', command: 'activate' },
{ keys: ['DELETE', 'BACKSPACE'], type: 'function', command: 'delete' },
{ keys: ['n'], type: 'function', command: 'next_link' },
{ keys: ['b'], type: 'function', command: 'previous_link' },
{ keys: ['o'], type: 'function', command: 'open_link' },
{ keys: [' '], type: 'prompt', command: 'todo toggle $n' },
{ keys: ['tc'], type: 'function', command: 'toggle_console' },
{ keys: ['tm'], type: 'function', command: 'toggle_metadata' },
{ keys: ['ti'], type: 'function', command: 'toggle_ids' },
{ keys: ['/'], type: 'prompt', command: 'search ""', cursorPosition: -2 },
{ keys: ['mn'], type: 'prompt', command: 'mknote ""', cursorPosition: -2 },
{ keys: ['mt'], type: 'prompt', command: 'mktodo ""', cursorPosition: -2 },
{ keys: ['mb'], type: 'prompt', command: 'mkbook ""', cursorPosition: -2 },
{ keys: ['yn'], type: 'prompt', command: 'cp $n ""', cursorPosition: -2 },
{ keys: ['dn'], type: 'prompt', command: 'mv $n ""', cursorPosition: -2 },
];
// Filter the keymap item by command so that items in keymap.json can override
// the default ones.
const itemsByCommand: Record<string, KeyMapItem> = {};
for (let i = 0; i < defaultKeyMap.length; i++) {
itemsByCommand[defaultKeyMap[i].command] = defaultKeyMap[i];
}
const filePath = `${Setting.value('profileDir')}/keymap.json`;
if (await pathExists(filePath)) {
try {
let configString = await readFile(filePath, 'utf-8');
configString = configString.replace(/^\s*\/\/.*/, ''); // Strip off comments
const keymap = JSON.parse(configString);
for (let keymapIndex = 0; keymapIndex < keymap.length; keymapIndex++) {
const item = keymap[keymapIndex];
itemsByCommand[item.command] = item;
}
} catch (error) {
let msg = error.message ? error.message : '';
msg = `Could not load keymap ${filePath}\n${msg}`;
error.message = msg;
throw error;
}
}
const output = [];
for (const n in itemsByCommand) {
if (!itemsByCommand.hasOwnProperty(n)) continue;
output.push(itemsByCommand[n]);
}
// Map reserved shortcuts to their equivalent key
// https://github.com/cronvel/terminal-kit/issues/101
for (let i = 0; i < output.length; i++) {
const newKeys = output[i].keys.map(k => {
k = k.replace(/CTRL_H/g, 'BACKSPACE');
k = k.replace(/CTRL_I/g, 'TAB');
k = k.replace(/CTRL_M/g, 'ENTER');
return k;
});
output[i].keys = newKeys;
}
return output;
}
public async commandList(argv: string[]) {
if (argv.length && argv[0] === 'batch') {
const commands = [];
const commandLines = splitCommandBatch(await readFile(argv[1], 'utf-8'));
for (const commandLine of commandLines) {
if (!commandLine.trim()) continue;
const splitted = splitCommandString(commandLine.trim());
commands.push(splitted);
}
return commands;
} else {
return [argv];
}
}
// We need this special case here because by the time the `version` command
// runs, the keychain has already been setup.
public checkIfKeychainEnabled(argv: string[]) {
return argv.indexOf('version') < 0;
}
public async start(argv: string[]) {
const keychainEnabled = this.checkIfKeychainEnabled(argv);
argv = await super.start(argv, { keychainEnabled });
cliUtils.setStdout((object: any) => {
return this.stdout(object);
});
this.initRedux();
// If we have some arguments left at this point, it's a command
// so execute it.
if (argv.length) {
this.gui_ = this.dummyGui();
this.currentFolder_ = await Folder.load(Setting.value('activeFolderId'));
await this.applySettingsSideEffects();
try {
const commands = await this.commandList(argv);
for (const command of commands) {
await this.execCommand(command);
}
} catch (error) {
if (this.showStackTraces_) {
console.error(error);
} else {
// eslint-disable-next-line no-console
console.info(error.message);
}
process.exit(1);
}
await Setting.saveAll();
// Need to call exit() explicitly, otherwise Node wait for any timeout to complete
// https://stackoverflow.com/questions/18050095
process.exit(0);
} else {
// Otherwise open the GUI
const keymap = await this.loadKeymaps();
const AppGui = require('./app-gui.js');
this.gui_ = new AppGui(this, this.store(), keymap);
this.gui_.setLogger(this.logger());
await this.gui_.start();
// Since the settings need to be loaded before the store is created, it will never
// receive the SETTING_UPDATE_ALL even, which mean state.settings will not be
// initialised. So we manually call dispatchUpdateAll() to force an update.
Setting.dispatchUpdateAll();
await refreshFolders((action: any) => this.store().dispatch(action));
const tags = await Tag.allWithNotes();
ResourceService.runInBackground();
RevisionService.instance().runInBackground();
this.dispatch({
type: 'TAG_UPDATE_ALL',
items: tags,
});
this.store().dispatch({
type: 'FOLDER_SELECT',
id: Setting.value('activeFolderId'),
});
this.startRotatingLogMaintenance(Setting.value('profileDir'));
}
}
}
let application_: Application = null;
function app() {
if (application_) return application_;
application_ = new Application();
return application_;
}
export default app;

View File

@@ -1,4 +1,4 @@
const { app } = require('./app.js');
const app = require('./app').default;
const Note = require('@joplin/lib/models/Note').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Tag = require('@joplin/lib/models/Tag').default;

View File

@@ -1,33 +1,34 @@
const BaseCommand = require('./base-command').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
import BaseCommand from './base-command';
import BaseItem from '@joplin/lib/models/BaseItem';
import BaseModel from '@joplin/lib/BaseModel';
const { toTitleCase } = require('@joplin/lib/string-utils.js');
const { reg } = require('@joplin/lib/registry.js');
const markdownUtils = require('@joplin/lib/markdownUtils').default;
const Database = require('@joplin/lib/database').default;
const shim = require('@joplin/lib/shim').default;
import { reg } from '@joplin/lib/registry.js';
import markdownUtils, { MarkdownTableRow } from '@joplin/lib/markdownUtils';
import Database from '@joplin/lib/database';
import shim from '@joplin/lib/shim';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'apidoc <file>';
}
description() {
public override description() {
return 'Build the API doc';
}
enabled() {
public override enabled() {
return false;
}
createPropertiesTable(tableFields) {
private createPropertiesTable(tableFields: MarkdownTableRow[]) {
const headers = [
{ name: 'name', label: 'Name' },
{
name: 'type',
label: 'Type',
filter: value => {
return Database.enumName('fieldType', value);
filter: (value: string|number) => {
const valueAsNumber = typeof value === 'number' ? value : parseInt(value, 10);
return Database.enumName('fieldType', valueAsNumber);
},
},
{ name: 'description', label: 'Description' },
@@ -36,7 +37,7 @@ class Command extends BaseCommand {
return markdownUtils.createMarkdownTable(headers, tableFields);
}
async action(args) {
public override async action(args: any) {
const models = [
{
type: BaseModel.TYPE_NOTE,

View File

@@ -1,19 +1,19 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import shim from '@joplin/lib/shim';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'attach <note> <file>';
}
description() {
public override description() {
return _('Attaches the given file to the note.');
}
async action(args) {
public override async action(args: any) {
const title = args['note'];
const note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });

View File

@@ -1,24 +1,24 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import BaseItem from '@joplin/lib/models/BaseItem';
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'cat <note>';
}
description() {
public override description() {
return _('Displays the given note.');
}
options() {
public override options() {
return [['-v, --verbose', _('Displays the complete information about note.')]];
}
async action(args) {
public override async action(args: any) {
const title = args['note'];
const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });

View File

@@ -1,19 +1,20 @@
const BaseCommand = require('./base-command').default;
const { _, setLocale } = require('@joplin/lib/locale');
const { app } = require('./app.js');
const fs = require('fs-extra');
const Setting = require('@joplin/lib/models/Setting').default;
import BaseCommand from './base-command';
import { _, setLocale } from '@joplin/lib/locale';
import app from './app';
import * as fs from 'fs-extra';
import Setting, { AppType } from '@joplin/lib/models/Setting';
import { ReadStream } from 'tty';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'config [name] [value]';
}
description() {
public override description() {
return _('Gets or sets a config value. If [value] is not provided, it will show the value of [name]. If neither [name] nor [value] is provided, it will list the current configuration.');
}
options() {
public override options() {
return [
['-v, --verbose', _('Also displays unset and hidden config variables.')],
['--export', 'Writes all settings to STDOUT as JSON including secure variables.'],
@@ -21,11 +22,12 @@ class Command extends BaseCommand {
['--import-file <file>', 'Reads in settings from <file>. <file> must contain valid JSON.'],
];
}
async __importSettings(inputStream) {
return new Promise((resolve, reject) => {
private async __importSettings(inputStream: ReadStream|fs.ReadStream) {
return new Promise<void>((resolve, reject) => {
// being defensive and not attempting to settle twice
let isSettled = false;
const chunks = [];
const chunks: any = [];
inputStream.on('readable', () => {
let chunk;
@@ -64,13 +66,14 @@ class Command extends BaseCommand {
});
});
}
async action(args) {
public override async action(args: any) {
const verbose = args.options.verbose;
const isExport = args.options.export;
const isImport = args.options.import || args.options.importFile;
const importFile = args.options.importFile;
const renderKeyValue = name => {
const renderKeyValue = (name: string) => {
const md = Setting.settingMetadata(name);
let value = Setting.value(name);
if (typeof value === 'object' || Array.isArray(value)) value = JSON.stringify(value);
@@ -84,11 +87,11 @@ class Command extends BaseCommand {
};
if (isExport || (!isImport && !args.value)) {
const keys = Setting.keys(!verbose, 'cli');
const keys = Setting.keys(!verbose, AppType.Cli);
keys.sort();
if (isExport) {
const resultObj = keys.reduce((acc, key) => {
const resultObj = keys.reduce<Record<string, any>>((acc, key) => {
const value = Setting.value(key);
if (!verbose && !value) return acc;
acc[key] = value;
@@ -113,7 +116,7 @@ class Command extends BaseCommand {
}
if (isImport) {
let fileStream = process.stdin;
let fileStream: ReadStream|fs.ReadStream = process.stdin;
if (importFile) {
fileStream = fs.createReadStream(importFile, { autoClose: true });
}

View File

@@ -1,19 +1,19 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'cp <note> [notebook]';
}
description() {
public override description() {
return _('Duplicates the notes matching <note> to [notebook]. If no notebook is specified the note is duplicated in the current notebook.');
}
async action(args) {
public override async action(args: any) {
let folder = null;
if (args['notebook']) {
folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
@@ -28,7 +28,7 @@ class Command extends BaseCommand {
for (let i = 0; i < notes.length; i++) {
const newNote = await Note.copyToFolder(notes[i].id, folder.id);
Note.updateGeolocation(newNote.id);
void Note.updateGeolocation(newNote.id);
}
}
}

View File

@@ -1,38 +0,0 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Note = require('@joplin/lib/models/Note').default;
const time = require('@joplin/lib/time').default;
class Command extends BaseCommand {
usage() {
return 'done <note>';
}
description() {
return _('Marks a to-do as done.');
}
static async handleAction(commandInstance, args, isCompleted) {
const note = await app().loadItem(BaseModel.TYPE_NOTE, args.note);
commandInstance.encryptionCheck(note);
if (!note) throw new Error(_('Cannot find "%s".', args.note));
if (!note.is_todo) throw new Error(_('Note is not a to-do: "%s"', args.note));
const todoCompleted = !!note.todo_completed;
if (isCompleted === todoCompleted) return;
await Note.save({
id: note.id,
todo_completed: isCompleted ? time.unixMs() : 0,
});
}
async action(args) {
await Command.handleAction(this, args, true);
}
}
module.exports = Command;

View File

@@ -0,0 +1,39 @@
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Note from '@joplin/lib/models/Note';
import time from '@joplin/lib/time';
import { NoteEntity } from '@joplin/lib/services/database/types';
class Command extends BaseCommand {
public override usage() {
return 'done <note>';
}
public override description() {
return _('Marks a to-do as done.');
}
public static async handleAction(commandInstance: BaseCommand, args: any, isCompleted: boolean) {
const note: NoteEntity = await app().loadItem(BaseModel.TYPE_NOTE, args.note);
commandInstance.encryptionCheck(note);
if (!note) throw new Error(_('Cannot find "%s".', args.note));
if (!note.is_todo) throw new Error(_('Note is not a to-do: "%s"', args.note));
const todoCompleted = !!note.todo_completed;
if (isCompleted === todoCompleted) return;
await Note.save({
id: note.id,
todo_completed: isCompleted ? time.unixMs() : 0,
});
}
public override async action(args: any) {
await Command.handleAction(this, args, true);
}
}
module.exports = Command;

View File

@@ -1,22 +1,22 @@
const BaseCommand = require('./base-command').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
import BaseCommand from './base-command';
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'dump';
}
description() {
public override description() {
return 'Dumps the complete database as JSON.';
}
hidden() {
public override hidden() {
return true;
}
async action() {
public override async action() {
let items = [];
const folders = await Folder.all();
for (let i = 0; i < folders.length; i++) {

View File

@@ -1,24 +1,24 @@
const fs = require('fs-extra');
const BaseCommand = require('./base-command').default;
const { splitCommandString } = require('@joplin/utils');
const uuid = require('@joplin/lib/uuid').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const Note = require('@joplin/lib/models/Note').default;
const Setting = require('@joplin/lib/models/Setting').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
import * as fs from 'fs-extra';
import BaseCommand from './base-command';
import { splitCommandString } from '@joplin/utils';
import uuid from '@joplin/lib/uuid';
import app from './app';
import { _ } from '@joplin/lib/locale';
import Note from '@joplin/lib/models/Note';
import Setting from '@joplin/lib/models/Setting';
import BaseModel from '@joplin/lib/BaseModel';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'edit <note>';
}
description() {
public override description() {
return _('Edit note.');
}
async action(args) {
let tempFilePath = null;
public override async action(args: any) {
let tempFilePath: string|null = null;
const onFinishedEditing = async () => {
if (tempFilePath) fs.removeSync(tempFilePath);

View File

@@ -1,23 +0,0 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
class Command extends BaseCommand {
usage() {
return 'exit';
}
description() {
return _('Exits the application.');
}
compatibleUis() {
return ['gui'];
}
async action() {
await app().exit();
}
}
module.exports = Command;

View File

@@ -0,0 +1,23 @@
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
class Command extends BaseCommand {
public override usage() {
return 'exit';
}
public override description() {
return _('Exits the application.');
}
public override compatibleUis() {
return ['gui'];
}
public override async action() {
await app().exit();
}
}
module.exports = Command;

View File

@@ -1,25 +1,25 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const Setting = require('@joplin/lib/models/Setting').default;
const ReportService = require('@joplin/lib/services/ReportService').default;
const fs = require('fs-extra');
import BaseCommand from './base-command';
import app from './app';
import Setting from '@joplin/lib/models/Setting';
import ReportService from '@joplin/lib/services/ReportService';
import * as fs from 'fs-extra';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'export-sync-status';
}
description() {
public override description() {
return 'Export sync status';
}
hidden() {
public override hidden() {
return true;
}
async action() {
public override async action() {
const service = new ReportService();
const csv = await service.basicItemList({ format: 'csv' });
const csv = await service.basicItemList({ format: 'csv' }) as string;
const filePath = `${Setting.value('profileDir')}/syncReport-${new Date().getTime()}.csv`;
await fs.writeFileSync(filePath, csv);
this.stdout(`Sync status exported to ${filePath}`);

View File

@@ -1,19 +1,20 @@
const BaseCommand = require('./base-command').default;
const InteropService = require('@joplin/lib/services/interop/InteropService').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
import BaseCommand from './base-command';
import InteropService from '@joplin/lib/services/interop/InteropService';
import BaseModel from '@joplin/lib/BaseModel';
import app from './app';
import { _ } from '@joplin/lib/locale';
import { ExportOptions } from '@joplin/lib/services/interop/types';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'export <path>';
}
description() {
public override description() {
return _('Exports Joplin data to the given path. By default, it will export the complete database including notebooks, notes, tags and resources.');
}
options() {
public override options() {
const service = InteropService.instance();
const formats = service
.modules()
@@ -23,8 +24,8 @@ class Command extends BaseCommand {
return [['--format <format>', _('Destination format: %s', formats.join(', '))], ['--note <note>', _('Exports only the given note.')], ['--notebook <notebook>', _('Exports only the given notebook.')]];
}
async action(args) {
const exportOptions = {};
public override async action(args: any) {
const exportOptions: ExportOptions = {};
exportOptions.path = args.path;
exportOptions.format = args.options.format ? args.options.format : 'jex';
@@ -34,11 +35,11 @@ class Command extends BaseCommand {
if (args.options.note) {
const notes = await app().loadItems(BaseModel.TYPE_NOTE, args.options.note, { parent: app().currentFolder() });
if (!notes.length) throw new Error(_('Cannot find "%s".', args.options.note));
exportOptions.sourceNoteIds = notes.map(n => n.id);
exportOptions.sourceNoteIds = notes.map((n: any) => n.id);
} else if (args.options.notebook) {
const folders = await app().loadItems(BaseModel.TYPE_FOLDER, args.options.notebook);
if (!folders.length) throw new Error(_('Cannot find "%s".', args.options.notebook));
exportOptions.sourceFolderIds = folders.map(n => n.id);
exportOptions.sourceFolderIds = folders.map((n: any) => n.id);
}
const service = InteropService.instance();

View File

@@ -1,19 +1,19 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'geoloc <note>';
}
description() {
public override description() {
return _('Displays a geolocation URL for the note.');
}
async action(args) {
public override async action(args: any) {
const title = args['note'];
const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });

View File

@@ -1,19 +1,19 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
import BaseCommand from './base-command';
import app from './app';
const { renderCommandHelp } = require('./help-utils.js');
const { _ } = require('@joplin/lib/locale');
import { _ } from '@joplin/lib/locale';
const { cliUtils } = require('./cli-utils.js');
class Command extends BaseCommand {
usage() {
public override usage() {
return 'help [command]';
}
description() {
public override description() {
return _('Displays usage information.');
}
allCommands() {
private allCommands() {
const commands = app().commands(app().uiType());
const output = [];
for (const n in commands) {
@@ -29,7 +29,7 @@ class Command extends BaseCommand {
return output;
}
async action(args) {
public override async action(args: any) {
const stdoutWidth = app().commandStdoutMaxWidth();
if (args.command === 'shortcuts' || args.command === 'keymap') {
@@ -52,7 +52,7 @@ class Command extends BaseCommand {
for (let i = 0; i < keymap.length; i++) {
const item = keymap[i];
const keys = item.keys.map(k => (k === ' ' ? '(SPACE)' : k));
const keys = item.keys.map((k: string) => (k === ' ' ? '(SPACE)' : k));
rows.push([keys.join(', '), item.command]);
}

View File

@@ -1,20 +1,22 @@
const BaseCommand = require('./base-command').default;
const InteropService = require('@joplin/lib/services/interop/InteropService').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
import BaseCommand from './base-command';
import InteropService from '@joplin/lib/services/interop/InteropService';
import BaseModel from '@joplin/lib/BaseModel';
const { cliUtils } = require('./cli-utils.js');
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
import app from './app';
import { _ } from '@joplin/lib/locale';
import { ImportOptions } from '@joplin/lib/services/interop/types';
import { unique } from '@joplin/lib/array';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'import <path> [notebook]';
}
description() {
public override description() {
return _('Imports data into Joplin.');
}
options() {
public override options() {
const service = InteropService.instance();
const formats = service
.modules()
@@ -22,18 +24,18 @@ class Command extends BaseCommand {
.map(m => m.format);
return [
['--format <format>', _('Source format: %s', ['auto'].concat(formats).join(', '))],
['--format <format>', _('Source format: %s', ['auto'].concat(unique(formats)).join(', '))],
['-f, --force', _('Do not ask for confirmation.')],
['--output-format <output-format>', _('Output format: %s', 'md, html')],
];
}
async action(args) {
public override async action(args: any) {
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook));
const importOptions = {};
const importOptions: ImportOptions = {};
importOptions.path = args.path;
importOptions.format = args.options.format ? args.options.format : 'auto';
importOptions.destinationFolderId = folder ? folder.id : null;

View File

@@ -1,28 +1,28 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Setting = require('@joplin/lib/models/Setting').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Folder from '@joplin/lib/models/Folder';
import Setting from '@joplin/lib/models/Setting';
import Note from '@joplin/lib/models/Note';
const { sprintf } = require('sprintf-js');
const time = require('@joplin/lib/time').default;
import time from '@joplin/lib/time';
const { cliUtils } = require('./cli-utils.js');
class Command extends BaseCommand {
usage() {
public override usage() {
return 'ls [note-pattern]';
}
description() {
public override description() {
return _('Displays the notes in the current notebook. Use `ls /` to display the list of notebooks.');
}
enabled() {
public override enabled() {
return true;
}
options() {
public override options() {
return [
['-n, --limit <num>', _('Displays only the first top <num> notes.')],
['-s, --sort <field>', _('Sorts the item by <field> (eg. title, updated_time, created_time).')],
@@ -33,12 +33,12 @@ class Command extends BaseCommand {
];
}
async action(args) {
public override async action(args: any) {
const pattern = args['note-pattern'];
let items = [];
const options = args.options;
const queryOptions = {};
const queryOptions: any = {};
if (options.limit) queryOptions.limit = options.limit;
if (options.sort) {
queryOptions.orderBy = options.sort;

View File

@@ -1,5 +1,5 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Folder from '@joplin/lib/models/Folder';

View File

@@ -1,5 +1,5 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const app = require('./app').default;
const { _ } = require('@joplin/lib/locale');
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,5 +1,5 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const app = require('./app').default;
const { _ } = require('@joplin/lib/locale');
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,20 +1,20 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'mv <item> [notebook]';
}
description() {
public override description() {
return _('Moves the given <item> to [notebook]');
}
async action(args) {
public override async action(args: any) {
const pattern = args['item'];
const destination = args['notebook'];
let folder = null;

View File

@@ -1,20 +1,20 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'ren <item> <name>';
}
description() {
public override description() {
return _('Renames the given <item> (note or notebook) to <name>.');
}
async action(args) {
public override async action(args: any) {
const pattern = args['item'];
const name = args['name'];

View File

@@ -1,23 +1,23 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const Folder = require('@joplin/lib/models/Folder').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import Folder from '@joplin/lib/models/Folder';
import BaseModel from '@joplin/lib/BaseModel';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'rmbook <notebook>';
}
description() {
public override description() {
return _('Deletes the given notebook.');
}
options() {
public override options() {
return [['-f, --force', _('Deletes the notebook without asking for confirmation.')]];
}
async action(args) {
public override async action(args: any) {
const pattern = args['notebook'];
const force = args.options && args.options.force === true;

View File

@@ -1,23 +1,23 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const Note = require('@joplin/lib/models/Note').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import Note from '@joplin/lib/models/Note';
import BaseModel from '@joplin/lib/BaseModel';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'rmnote <note-pattern>';
}
description() {
public override description() {
return _('Deletes the notes matching <note-pattern>.');
}
options() {
public override options() {
return [['-f, --force', _('Deletes the notes without asking for confirmation.')]];
}
async action(args) {
public override async action(args: any) {
const pattern = args['note-pattern'];
const force = args.options && args.options.force === true;
@@ -26,7 +26,7 @@ class Command extends BaseCommand {
const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' });
if (!ok) return;
const ids = notes.map(n => n.id);
const ids = notes.map((n: any) => n.id);
await Note.batchDelete(ids);
}
}

View File

@@ -1,16 +1,16 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Database = require('@joplin/lib/database').default;
const Note = require('@joplin/lib/models/Note').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
import Database from '@joplin/lib/database';
import Note from '@joplin/lib/models/Note';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'set <note> <name> [value]';
}
description() {
public override description() {
const fields = Note.fields();
const s = [];
for (let i = 0; i < fields.length; i++) {
@@ -22,7 +22,7 @@ class Command extends BaseCommand {
return _('Sets the property <name> of the given <note> to the given [value]. Possible properties are:\n\n%s', s.join(', '));
}
async action(args) {
public override async action(args: any) {
const title = args['note'];
const propName = args['name'];
let propValue = args['value'];
@@ -36,7 +36,7 @@ class Command extends BaseCommand {
const timestamp = Date.now();
const newNote = {
const newNote: any = {
id: notes[i].id,
type_: notes[i].type_,
updated_time: timestamp,

View File

@@ -1,5 +1,5 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const app = require('./app').default;
const Setting = require('@joplin/lib/models/Setting').default;
const { _ } = require('@joplin/lib/locale');
const ReportService = require('@joplin/lib/services/ReportService').default;

View File

@@ -7,7 +7,7 @@ import Synchronizer from '@joplin/lib/Synchronizer';
import { masterKeysWithoutPassword } from '@joplin/lib/services/e2ee/utils';
import { appTypeToLockType } from '@joplin/lib/services/synchronizer/LockHandler';
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
import app from './app';
const { OneDriveApiNodeUtils } = require('@joplin/lib/onedrive-api-node-utils.js');
import { reg } from '@joplin/lib/registry';
const { cliUtils } = require('./cli-utils.js');

View File

@@ -1,5 +1,5 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const app = require('./app').default;
const { _ } = require('@joplin/lib/locale');
const Tag = require('@joplin/lib/models/Tag').default;
const BaseModel = require('@joplin/lib/BaseModel').default;

View File

@@ -1,5 +1,5 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const app = require('./app').default;
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,22 +1,22 @@
const BaseCommand = require('./base-command').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');
const BaseModel = require('@joplin/lib/BaseModel').default;
import BaseCommand from './base-command';
import app from './app';
import { _ } from '@joplin/lib/locale';
import BaseModel from '@joplin/lib/BaseModel';
class Command extends BaseCommand {
usage() {
public override usage() {
return 'use <notebook>';
}
description() {
public override description() {
return _('Switches to [notebook] - all further operations will happen within this notebook.');
}
compatibleUis() {
public override compatibleUis() {
return ['cli'];
}
async action(args) {
public override async action(args: any) {
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
if (!folder) throw new Error(_('Cannot find "%s".', args['notebook']));
app().switchCurrentFolder(folder);

View File

@@ -1,17 +1,17 @@
const BaseCommand = require('./base-command').default;
import BaseCommand from './base-command';
const { _ } = require('@joplin/lib/locale');
const versionInfo = require('@joplin/lib/versionInfo').default;
class Command extends BaseCommand {
usage() {
public override usage() {
return 'version';
}
description() {
public override description() {
return _('Displays version information');
}
async action() {
public override async action() {
this.stdout(versionInfo(require('./package.json'), {}).message);
}
}

View File

@@ -10,7 +10,7 @@ if (compareVersion(nodeVersion, '10.0.0') < 0) {
process.exit(1);
}
const { app } = require('./app.js');
const app = require('./app').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Resource = require('@joplin/lib/models/Resource').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;

View File

@@ -1,4 +1,4 @@
const { app } = require('../app');
import app from '../app';
import Folder from '@joplin/lib/models/Folder';
import BaseCommand from '../base-command';
import setupCommand from '../setupCommand';

View File

@@ -1,3 +1,3 @@
#!/bin/bash
set -e
yarn run build && NODE_PATH=build node build/build-doc.js
yarn build && NODE_PATH=build node build/build-doc.js

View File

@@ -1,3 +1,3 @@
#!/bin/bash
set -e
yarn run build && NODE_PATH="build/" node build/cli-integration-tests.js
yarn build && NODE_PATH="build/" node build/cli-integration-tests.js

View File

@@ -2,7 +2,7 @@
# Start the server with:
#
# JOPLIN_IS_TESTING=1 yarn run start-dev
# JOPLIN_IS_TESTING=1 yarn start-dev
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

View File

@@ -1,4 +1,4 @@
#!/bin/bash
#
set -e
yarn run build && NODE_PATH="build/" node build/fuzzing.js
yarn build && NODE_PATH="build/" node build/fuzzing.js

View File

@@ -3,6 +3,7 @@ const { shimInit } = require('@joplin/lib/shim-init-node.js');
const shim = require('@joplin/lib/shim').default;
const sharp = require('sharp');
const nodeSqlite = require('sqlite3');
require('../../jest.base-setup.js')();
let keytar;
try {

View File

@@ -35,19 +35,19 @@
],
"owner": "Laurent Cozic"
},
"version": "2.13.1",
"version": "2.14.0",
"bin": "./main.js",
"engines": {
"node": ">=10.0.0"
},
"dependencies": {
"@joplin/lib": "~2.13",
"@joplin/renderer": "~2.13",
"@joplin/utils": "~2.13",
"@joplin/lib": "~2.14",
"@joplin/renderer": "~2.14",
"@joplin/utils": "~2.14",
"aws-sdk": "2.1340.0",
"chalk": "4.1.2",
"compare-version": "0.1.2",
"fs-extra": "11.1.1",
"fs-extra": "11.2.0",
"html-entities": "1.4.0",
"image-type": "3.1.0",
"keytar": "7.9.0",
@@ -57,9 +57,9 @@
"proper-lockfile": "4.1.2",
"read-chunk": "2.1.0",
"server-destroy": "1.0.1",
"sharp": "0.32.6",
"sharp": "0.33.2",
"sprintf-js": "1.1.3",
"sqlite3": "5.1.6",
"sqlite3": "5.1.7",
"string-padding": "1.0.2",
"strip-ansi": "6.0.1",
"tcp-port-used": "1.0.2",
@@ -70,10 +70,10 @@
"yargs-parser": "21.1.1"
},
"devDependencies": {
"@joplin/tools": "~2.13",
"@types/fs-extra": "11.0.3",
"@types/jest": "29.5.5",
"@types/node": "18.18.8",
"@joplin/tools": "~2.14",
"@types/fs-extra": "11.0.4",
"@types/jest": "29.5.8",
"@types/node": "18.19.8",
"@types/proper-lockfile": "^4.1.2",
"gulp": "4.0.2",
"jest": "29.7.0",

View File

@@ -40,6 +40,10 @@ describe('HtmlToMd', () => {
htmlToMdOptions.preserveNestedTables = true;
}
if (htmlFilename.indexOf('text_color') === 0) {
htmlToMdOptions.preserveColorStyles = true;
}
const html = await readFile(htmlPath, 'utf8');
let expectedMd = await readFile(mdPath, 'utf8');

View File

@@ -1,5 +1,6 @@
import MarkupToHtml, { MarkupLanguage, RenderResult } from '@joplin/renderer/MarkupToHtml';
import MarkupToHtml, { MarkupLanguage } from '@joplin/renderer/MarkupToHtml';
import { RenderResult } from '@joplin/renderer/types';
describe('MarkupToHtml', () => {

View File

@@ -291,4 +291,29 @@ describe('MdToHtml', () => {
expect(html.html).toContain(opening + trimmedTex + closing);
}
});
it('should render inline KaTeX after a numbered equation', async () => {
const mdToHtml = newTestMdToHtml();
// This test is intended to verify that inline KaTeX renders correctly
// after creating a numbered equation with \begin{align}...\end{align}.
//
// See https://github.com/laurent22/joplin/issues/9455 for details.
const markdown = [
'$$',
'\\begin{align}\\text{Block}\\end{align}',
'$$',
'',
'$\\text{Inline}$',
].join('\n');
const { html } = await mdToHtml.render(markdown, null, { bodyOnly: true });
// Because we don't control the output of KaTeX, this test should be as general as
// possible while still verifying that rendering (without an error) occurs.
// Should have rendered the inline and block content without errors
expect(html).toContain('Inline</span>');
expect(html).toContain('Block</span>');
});
});

View File

@@ -7,7 +7,7 @@
<en-note><div>Plain note</div></en-note>]]></content><created>20201223T163948Z</created><updated>20201223T163953Z</updated><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note><note><title>Note 2</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note><div><div><br/></div><table style="border-collapse: collapse; min-width: 100%;"><colgroup><col style="width: 130px;"/><col style="width: 130px;"/><col style="width: 130px;"/></colgroup><tbody><tr<td style="width: 130px; padding: 8px; border: 1px solid;"><div>test</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>test</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div><br/></div></td></tr><tr><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bl</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bla</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bla</div></td></tr></tbody></table><div><br/></div></div><div><br/></div></en-note>]]></content><created>20201223T164010Z</created><updated>20201223T164023Z</updated><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note><note><title>plain note 2</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<en-note><div><div><br/></div><table style="border-collapse: collapse; min-width: 100%;"><colgroup><col style="width: 130px;"/><col style="width: 130px;"/><col style="width: 130px;"/></colgroup><tbody><tr<td style="width: 130px; padding: 8px; border: 1px solid;"><div>test</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>test</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div><br/></div></td></tr><tr><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bl</div></t><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bla</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bla</div></td></tr></tbody></table><div><br/></div></div><div><br/></div></en-note>]]></content><created>20201223T164010Z</created><updated>20201223T164023Z</updated><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note><note><title>plain note 2</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note><div><br/></div></en-note>]]></content><created>20201223T164236Z</created><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note></en-export>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export4.dtd">
<en-export export-date="20231224T151504Z" application="Evernote" version="10.68.2">
<note>
<title>Note 1</title>
<created>20160730T164129Z</created>
<updated>20231224T151443Z</updated>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div><a href="evernote:///view/5223870/s49/9cd5e810-fa03-429a-8194-ab847f2f1ab2/c99d9e01-ca35-4c75-ba63-f0c0ef97787d/" rel="noopener noreferrer" rev="en_rl_none">Note 2</a><a href="evernote:///view/5223870/s49/9cd5e810-fa03-429a-8194-ab847f2f1ab2/c99d9e01-ca35-4c75-ba63-f0c0ef97787d/" rel="noopener noreferrer" rev="en_rl_none">Note 3</a></div></en-note> ]]>
</content>
</note>
<note>
<title>Note 2</title>
<created>20160730T111759Z</created>
<updated>20160730T111807Z</updated>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div>Testing</div></en-note> ]]>
</content>
</note>
<note>
<title>Note 3</title>
<created>20160730T111759Z</created>
<updated>20160730T111807Z</updated>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div><a href="evernote:///view/5223870/s49/9cd5e810-fa03-429a-8194-ab847f2f1ab2/c99d9e01-ca35-4c75-ba63-f0c0ef97787d/" rel="noopener noreferrer" rev="en_rl_none">Ambiguous note</a></div></en-note> ]]>
</content>
</note>
<note>
<title>Ambiguous note</title>
<created>20160730T111759Z</created>
<updated>20160730T111807Z</updated>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div>Testing</div></en-note> ]]>
</content>
</note>
<note>
<title>Ambiguous note</title>
<created>20160730T111759Z</created>
<updated>20160730T111807Z</updated>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div>Testing</div></en-note> ]]>
</content>
</note>
</en-export>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
<table>
<div></div> <!-- INVALID! -->
<tr>
<td>one</td>
<td>two</td>
</tr>
<tr>
<div></div> <!-- INVALID! -->
<td>three</td>
<td>four</td>
</tr>
</table>

View File

@@ -0,0 +1,4 @@
| | |
| --- | --- |
| one | two |
| three | four |

View File

@@ -0,0 +1,9 @@
<p>
SVG image:
<img src="data:image/svg+xml;utf8,
<svg width=&quot;1700&quot; height=&quot;1536&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;>
<path d=&quot;m0,0%20l100,1000%20l200,0%20z&quot;/>
</svg>"/>
</p>
<p>PNG image: <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAR0lEQVQIW4XLMQoAIQwF0flpBEHwtOlUsPW6gZTushfYqd8IuHtvxhhI4pyD1lq3905EYGa01tB9m3N+IjNxd/S711oppfAAOjQiFPMurHkAAAAASUVORK5CYII="></p>

View File

@@ -0,0 +1,3 @@
SVG image: ![](data:image/svg+xml;utf8,%0A%09%09<svg%20width="1700"%20height="1536"%20xmlns="http://www.w3.org/2000/svg">%0A%09%09%09<path%20d="m0,0%20l100,1000%20l200,0%20z"/>%0A%09%09</svg>)
PNG image: ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAR0lEQVQIW4XLMQoAIQwF0flpBEHwtOlUsPW6gZTushfYqd8IuHtvxhhI4pyD1lq3905EYGa01tB9m3N+IjNxd/S711oppfAAOjQiFPMurHkAAAAASUVORK5CYII=)

View File

@@ -1,10 +1,10 @@
<body>
<table border="5px" bordercolor="#8707B0">
<table>
<tr>
<td>Left side of the main table</td>
<td>
<table border="5px" bordercolor="#F35557">
<h4 align="center">Nested Table</h4>
<table>
<b>Nested Table</b>
<tr>
<td>nested table C1</td>
<td>nested table C2</td>

View File

@@ -1 +1 @@
<table border="5px" bordercolor="#8707B0"><tbody><tr><td>Left side of the main table</td><td><h4 align="center">Nested Table</h4><table border="5px" bordercolor="#F35557"><tbody><tr><td>nested table C1</td><td>nested table C2</td></tr><tr><td>nested table</td><td>nested table</td></tr></tbody></table></td></tr></tbody></table>
<table><tbody><tr><td>Left side of the main table</td><td><b>Nested Table</b><table><tbody><tr><td>nested table C1</td><td>nested table C2</td></tr><tr><td>nested table</td><td>nested table</td></tr></tbody></table></td></tr></tbody></table>

View File

@@ -0,0 +1,31 @@
<div id="rendered-md">
<table class="jop-noMdConv">
<thead class="jop-noMdConv">
<tr class="jop-noMdConv">
<th class="jop-noMdConv">Code</th>
<th class="jop-noMdConv">Description</th>
</tr>
<tr class="jop-noMdConv">
<td class="jop-noMdConv">
<pre class="jop-noMdConv"><code class="jop-noMdConv">const test = "hello";
// Another line
console.log('Test...');
// Blank lines
// Should not break things.</code></pre>
</td>
<td class="jop-noMdConv">abcda</td>
</tr>
<tr class="jop-noMdConv">
<td class="jop-noMdConv">
<pre class="jop-noMdConv"><code class="jop-noMdConv">const test = "hello";</code></pre>
</td>
<td class="jop-noMdConv">abcd</td>
</tr>
</thead>
</table>
</div>

View File

@@ -0,0 +1,10 @@
<table class="jop-noMdConv"><thead class="jop-noMdConv"><tr class="jop-noMdConv"><th class="jop-noMdConv">Code</th><th class="jop-noMdConv">Description</th></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";
<!-- -->
// Another line
console.log('Test...');
<!-- -->
// Blank lines
<!-- -->
<!-- -->
<!-- -->
// Should not break things.</code></pre></td><td class="jop-noMdConv">abcda</td></tr><tr class="jop-noMdConv"><td class="jop-noMdConv"><pre class="jop-noMdConv"><code class="">const test = "hello";</code></pre></td><td class="jop-noMdConv">abcd</td></tr></thead></table>

View File

@@ -0,0 +1 @@
<p>Text <span style="color: #fff000;">Text</span></p>

View File

@@ -0,0 +1 @@
Text <span style="color: #fff000;">Text</span>

View File

@@ -0,0 +1,2 @@
<p>SVG image: <img src="data:image/svg+xml;utf8,%3Csvg%20width=%221700%22%20height=%221536%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%20%3Cpath%20d=%22m0,0%20l100,1000%20l200,0%20z%22/%3E%20%3C/svg%3E" alt=""></p>
<p>PNG image: <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAR0lEQVQIW4XLMQoAIQwF0flpBEHwtOlUsPW6gZTushfYqd8IuHtvxhhI4pyD1lq3905EYGa01tB9m3N+IjNxd/S711oppfAAOjQiFPMurHkAAAAASUVORK5CYII=" alt=""></p>

View File

@@ -0,0 +1,3 @@
SVG image: ![](data:image/svg+xml;utf8,<svg%20width="1700"%20height="1536"%20xmlns="http://www.w3.org/2000/svg">%20<path%20d="m0,0%20l100,1000%20l200,0%20z"/>%20</svg>)
PNG image: ![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAR0lEQVQIW4XLMQoAIQwF0flpBEHwtOlUsPW6gZTushfYqd8IuHtvxhhI4pyD1lq3905EYGa01tB9m3N+IjNxd/S711oppfAAOjQiFPMurHkAAAAASUVORK5CYII=)

View File

@@ -0,0 +1,3 @@
<nav class="table-of-contents"><ul><li><a href="#test">test</a></li><li><a href="#test-2">test</a></li><li><a href="#test2">test2</a></li></ul></nav><h1 id="test">test</h1>
<h1 id="test-2">test</h1>
<h1 id="test2">test2</h1>

View File

@@ -0,0 +1,5 @@
[toc]
# test
# test
# test2

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

View File

@@ -1,5 +1,5 @@
import PluginRunner from '../../../app/services/plugins/PluginRunner';
import PluginService from '@joplin/lib/services/plugins/PluginService';
import PluginService, { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
import { ContentScriptType } from '@joplin/lib/services/plugins/api/types';
import MdToHtml from '@joplin/renderer/MdToHtml';
import shim from '@joplin/lib/shim';
@@ -304,4 +304,33 @@ describe('services_PluginService', () => {
expect(JSON.parse(folders[0].title)).toBe(expectedPath);
}));
it('should uninstall multiple plugins', async () => {
const service = newPluginService();
const pluginId1 = 'org.joplinapp.FirstJplPlugin';
const pluginId2 = 'org.joplinapp.plugins.TocDemo';
const pluginPath1 = `${testPluginDir}/jpl_test/${pluginId1}.jpl`;
const pluginPath2 = `${testPluginDir}/toc/${pluginId2}.jpl`;
await service.installPlugin(pluginPath1);
await service.installPlugin(pluginPath2);
// Both should be installed
expect(await fs.pathExists(`${Setting.value('pluginDir')}/${pluginId1}.jpl`)).toBe(true);
expect(await fs.pathExists(`${Setting.value('pluginDir')}/${pluginId2}.jpl`)).toBe(true);
const pluginSettings: PluginSettings = {
[pluginId1]: { enabled: true, deleted: true, hasBeenUpdated: false },
[pluginId2]: { enabled: true, deleted: true, hasBeenUpdated: false },
};
const newPluginSettings = await service.uninstallPlugins(pluginSettings);
// Should have deleted plugins
expect(await fs.pathExists(`${Setting.value('pluginDir')}/${pluginId1}.jpl`)).toBe(false);
expect(await fs.pathExists(`${Setting.value('pluginDir')}${pluginId2}.jpl`)).toBe(false);
// Should clear deleted plugins from settings
expect(newPluginSettings[pluginId1]).toBe(undefined);
expect(newPluginSettings[pluginId2]).toBe(undefined);
});
});

View File

@@ -1,13 +1,12 @@
import { installDefaultPlugins, getDefaultPluginsInstallState, setSettingsForDefaultPlugins, checkPreInstalledDefaultPlugins } from '@joplin/lib/services/plugins/defaultPlugins/defaultPluginsUtils';
import { afterDefaultPluginsLoaded, getDefaultPluginPathsAndSettings } from '@joplin/lib/services/plugins/defaultPlugins/defaultPluginsUtils';
import PluginRunner from '../../../app/services/plugins/PluginRunner';
import { pathExists } from 'fs-extra';
import { checkThrow, setupDatabaseAndSynchronizer, supportDir, switchClient } from '@joplin/lib/testing/test-utils';
import PluginService, { defaultPluginSetting, DefaultPluginsInfo, PluginSettings } from '@joplin/lib/services/plugins/PluginService';
import PluginService, { defaultPluginSetting, DefaultPluginsInfo } from '@joplin/lib/services/plugins/PluginService';
import Setting from '@joplin/lib/models/Setting';
const testPluginDir = `${supportDir}/plugins`;
const testDefaultPluginsDir = `${supportDir}/testDefaultPlugins`;
function newPluginService(appVersion = '1.4') {
function newPluginService(appVersion = '2.4') {
const runner = new PluginRunner();
const service = new PluginService();
service.initialize(
@@ -27,232 +26,196 @@ function newPluginService(appVersion = '1.4') {
describe('defaultPluginsUtils', () => {
const pluginsId = ['joplin.plugin.ambrt.backlinksToNote', 'org.joplinapp.plugins.ToggleSidebars'];
const defaultPluginsInfo = {
'joplin.plugin.ambrt.backlinksToNote': {},
'org.joplinapp.plugins.ToggleSidebars': {},
};
beforeEach(async () => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
});
it('should install default plugins with no previous default plugins installed', (async () => {
const testPluginDir = `${supportDir}/pluginRepo/plugins`;
it('should load default plugins when not previously installed', (async () => {
Setting.setValue('installedDefaultPlugins', []);
const service = newPluginService('2.1');
const pluginSettings = service.unserializePluginSettings(Setting.value('plugins.states'));
const newPluginsSettings = await installDefaultPlugins(service, testPluginDir, pluginsId, pluginSettings);
for (const pluginId of pluginsId) {
expect(pluginSettings[pluginId]).toBeFalsy();
}
const installedPluginPath1 = `${Setting.value('pluginDir')}/${pluginsId[0]}.jpl`;
const installedPluginPath2 = `${Setting.value('pluginDir')}/${pluginsId[1]}.jpl`;
expect(await pathExists(installedPluginPath1)).toBe(true);
expect(await pathExists(installedPluginPath2)).toBe(true);
expect(newPluginsSettings[pluginsId[0]]).toMatchObject(defaultPluginSetting());
expect(newPluginsSettings[pluginsId[1]]).toMatchObject(defaultPluginSetting());
const pluginPathsAndNewSettings = await getDefaultPluginPathsAndSettings(
testDefaultPluginsDir, defaultPluginsInfo, pluginSettings, service,
);
for (const pluginId of pluginsId) {
expect(
pluginPathsAndNewSettings.pluginSettings[pluginId],
).toMatchObject(defaultPluginSetting());
}
}));
it('should install default plugins with previous default plugins installed', (async () => {
const testPluginDir = `${supportDir}/pluginRepo/plugins`;
it('should keep already created default plugins disabled with previous default plugins installed', (async () => {
Setting.setValue('installedDefaultPlugins', ['org.joplinapp.plugins.ToggleSidebars']);
Setting.setValue('plugins.states', {
'org.joplinapp.plugins.ToggleSidebars': { ...defaultPluginSetting(), enabled: false },
});
const service = newPluginService('2.1');
const pluginSettings = service.unserializePluginSettings(Setting.value('plugins.states'));
const pluginPathsAndNewSettings = await getDefaultPluginPathsAndSettings(testDefaultPluginsDir, defaultPluginsInfo, pluginSettings, service);
const newPluginsSettings = await installDefaultPlugins(service, testPluginDir, pluginsId, pluginSettings);
const installedPluginPath1 = `${Setting.value('pluginDir')}/${pluginsId[0]}.jpl`;
const installedPluginPath2 = `${Setting.value('pluginDir')}/${pluginsId[1]}.jpl`;
expect(await pathExists(installedPluginPath1)).toBe(true);
expect(await pathExists(installedPluginPath2)).toBe(false);
expect(newPluginsSettings[pluginsId[0]]).toMatchObject(defaultPluginSetting());
expect(newPluginsSettings[pluginsId[1]]).toBeUndefined();
// Should still be disabled
expect(
pluginPathsAndNewSettings.pluginSettings['org.joplinapp.plugins.ToggleSidebars'].enabled,
).toBe(false);
}));
it('should get default plugins install state', (async () => {
const testCases = [
{
'installedDefaultPlugins': [''],
'loadingPlugins': [`${testPluginDir}/simple`, `${testPluginDir}/jpl_test/org.joplinapp.FirstJplPlugin.jpl`],
'plugin1DefaultState': defaultPluginSetting(),
'plugin2DefaultState': defaultPluginSetting(),
'installedDefaultPlugins1': true,
'installedDefaultPlugins2': true,
},
{
'installedDefaultPlugins': [''],
'loadingPlugins': [`${testPluginDir}/simple`],
'plugin1DefaultState': defaultPluginSetting(),
'plugin2DefaultState': undefined,
'installedDefaultPlugins1': true,
'installedDefaultPlugins2': false,
},
{
'installedDefaultPlugins': ['org.joplinapp.plugins.Simple'],
'loadingPlugins': [`${testPluginDir}/simple`, `${testPluginDir}/jpl_test/org.joplinapp.FirstJplPlugin.jpl`],
'plugin1DefaultState': undefined,
'plugin2DefaultState': defaultPluginSetting(),
'installedDefaultPlugins1': true,
'installedDefaultPlugins2': true,
},
{
'installedDefaultPlugins': ['org.joplinapp.plugins.Simple'],
'loadingPlugins': [`${testPluginDir}/simple`],
'plugin1DefaultState': undefined,
'plugin2DefaultState': undefined,
'installedDefaultPlugins1': true,
'installedDefaultPlugins2': false,
},
];
for (const testCase of testCases) {
const service = newPluginService();
const pluginsId = ['org.joplinapp.plugins.Simple', 'org.joplinapp.FirstJplPlugin'];
Setting.setValue('installedDefaultPlugins', testCase.installedDefaultPlugins);
await service.loadAndRunPlugins(testCase.loadingPlugins, {});
// setting installedDefaultPlugins state
const defaultInstallStates: PluginSettings = getDefaultPluginsInstallState(service, pluginsId);
expect(defaultInstallStates[pluginsId[0]]).toStrictEqual(testCase.plugin1DefaultState);
expect(defaultInstallStates[pluginsId[1]]).toStrictEqual(testCase.plugin2DefaultState);
const installedDefaultPlugins = Setting.value('installedDefaultPlugins');
expect(installedDefaultPlugins.includes(pluginsId[0])).toBe(testCase.installedDefaultPlugins1);
expect(installedDefaultPlugins.includes(pluginsId[1])).toBe(testCase.installedDefaultPlugins2);
}
}));
it('should check pre-installed default plugins', (async () => {
// with previous pre-installed default plugins
Setting.setValue('installedDefaultPlugins', ['']);
let pluginSettings, installedDefaultPlugins;
pluginSettings = { [pluginsId[0]]: defaultPluginSetting() };
checkPreInstalledDefaultPlugins(pluginsId, pluginSettings);
installedDefaultPlugins = Setting.value('installedDefaultPlugins');
expect(installedDefaultPlugins.includes(pluginsId[0])).toBe(true);
expect(installedDefaultPlugins.includes(pluginsId[1])).toBe(false);
// with no previous pre-installed default plugins
Setting.setValue('installedDefaultPlugins', ['not-a-default-plugin']);
pluginSettings = {};
checkPreInstalledDefaultPlugins(pluginsId, pluginSettings);
installedDefaultPlugins = Setting.value('installedDefaultPlugins');
expect(installedDefaultPlugins.includes(pluginsId[0])).toBe(false);
expect(installedDefaultPlugins.includes(pluginsId[1])).toBe(false);
}));
const sampleJsBundlePlugin = `
/* joplin-manifest:
{
"id": "io.github.jackgruber.backup",
"manifest_version": 1,
"app_min_version": "1.4",
"name": "JS Bundle test",
"version": "1.0.0"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.settings.registerSettings({
path: {
value: "initial-path",
type: 2,
section: "backupSection",
public: true,
label: "Backup path",
},
})
},
});`;
it('should set initial settings for default plugins', async () => {
const service = newPluginService();
const pluginScript = `
/* joplin-manifest:
{
"id": "io.github.jackgruber.backup",
"manifest_version": 1,
"app_min_version": "1.4",
"name": "JS Bundle test",
"version": "1.0.0"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.settings.registerSettings({
path: {
value: "initial-path",
type: 2,
section: "backupSection",
public: true,
label: "Backup path",
},
})
},
});`;
const plugin = await service.loadPluginFromJsBundle('', pluginScript);
const plugin = await service.loadPluginFromJsBundle('', sampleJsBundlePlugin);
plugin.builtIn = true;
await service.runPlugin(plugin);
const runningPlugins = { 'io.github.jackgruber.backup': plugin };
const defaultPluginsInfo: DefaultPluginsInfo = {
'io.github.jackgruber.backup': {
version: '1.0.2',
settings: {
'path': `${Setting.value('profileDir')}`,
},
},
'plugin.calebjohn.rich-markdown': {
version: '0.8.3',
},
};
// with pre-installed default plugin
Setting.setValue('installedDefaultPlugins', ['io.github.jackgruber.backup']);
setSettingsForDefaultPlugins(defaultPluginsInfo);
const pluginSettings = { 'io.github.jackgruber.backup': defaultPluginSetting() };
await afterDefaultPluginsLoaded(
runningPlugins,
defaultPluginsInfo,
pluginSettings,
);
expect(Setting.value('plugin-io.github.jackgruber.backup.path')).toBe('initial-path');
await service.destroy();
// with no pre-installed default plugin
Setting.setValue('installedDefaultPlugins', ['']);
setSettingsForDefaultPlugins(defaultPluginsInfo);
await afterDefaultPluginsLoaded(
runningPlugins,
defaultPluginsInfo,
pluginSettings,
);
expect(Setting.value('plugin-io.github.jackgruber.backup.path')).toBe(`${Setting.value('profileDir')}`);
await service.destroy();
});
it('should not overwrite existing settings for a user-installed version of a built-in plugin', async () => {
const service = newPluginService();
const plugin = await service.loadPluginFromJsBundle('', sampleJsBundlePlugin);
plugin.builtIn = false;
await service.runPlugin(plugin);
const defaultPluginsInfo: DefaultPluginsInfo = {
'io.github.jackgruber.backup': {
settings: {
'path': 'overwrite?',
},
},
};
// No pre-installed default plugins
Setting.setValue('installedDefaultPlugins', []);
// The plugin is running and enabled
const runningPlugins = { 'io.github.jackgruber.backup': plugin };
const pluginSettings = { 'io.github.jackgruber.backup': defaultPluginSetting() };
await afterDefaultPluginsLoaded(
runningPlugins,
defaultPluginsInfo,
pluginSettings,
);
// Should not overwrite
expect(Setting.value('plugin-io.github.jackgruber.backup.path')).toBe('initial-path');
});
it('should support disabled-by-default plugins', async () => {
const service = newPluginService();
const plugin = await service.loadPluginFromJsBundle('', sampleJsBundlePlugin);
plugin.builtIn = false;
await service.runPlugin(plugin);
const defaultPluginsInfo: DefaultPluginsInfo = {
'joplin.plugin.ambrt.backlinksToNote': {
enabled: false,
},
'org.joplinapp.plugins.ToggleSidebars': {},
};
Setting.setValue('installedDefaultPlugins', []);
const { pluginSettings } = await getDefaultPluginPathsAndSettings(
testDefaultPluginsDir, defaultPluginsInfo, {}, service,
);
expect(pluginSettings).toMatchObject({
'joplin.plugin.ambrt.backlinksToNote': {
enabled: false,
deleted: false,
},
'org.joplinapp.plugins.ToggleSidebars': defaultPluginSetting(),
});
});
it('should not throw error on missing setting key', async () => {
const service = newPluginService();
const pluginScript = `
/* joplin-manifest:
{
"id": "io.github.jackgruber.backup",
"manifest_version": 1,
"app_min_version": "1.4",
"name": "JS Bundle test",
"version": "1.0.0"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.settings.registerSettings({
path: {
value: "initial-path",
type: 2,
section: "backupSection",
public: true,
label: "Backup path",
},
})
},
});`;
const plugin = await service.loadPluginFromJsBundle('', pluginScript);
const plugin = await service.loadPluginFromJsBundle('', sampleJsBundlePlugin);
plugin.builtIn = true;
await service.runPlugin(plugin);
const defaultPluginsInfo: DefaultPluginsInfo = {
'io.github.jackgruber.backup': {
version: '1.0.2',
settings: {
'path': `${Setting.value('profileDir')}`,
'missing-key1': 'someValue',
},
},
'plugin.calebjohn.rich-markdown': {
version: '0.8.3',
settings: {
'missing-key2': 'someValue',
},
@@ -260,9 +223,42 @@ describe('defaultPluginsUtils', () => {
};
Setting.setValue('installedDefaultPlugins', ['']);
expect(checkThrow(() => setSettingsForDefaultPlugins(defaultPluginsInfo))).toBe(false);
const pluginSettings = { 'io.github.jackgruber.backup': defaultPluginSetting() };
const runningPlugins = { 'io.github.jackgruber.backup': plugin };
expect(checkThrow(() => afterDefaultPluginsLoaded(runningPlugins, defaultPluginsInfo, pluginSettings))).toBe(false);
expect(Setting.value('plugin-io.github.jackgruber.backup.path')).toBe(`${Setting.value('profileDir')}`);
await service.destroy();
});
// Only returning not-yet-loaded plugins prevents non-default versions of built-in plugins
// from being overwritten by PluginService.
it('getDefaultPluginPathsAndSettings should return only plugins that haven\'t been loaded', async () => {
const service = newPluginService();
const testPluginId = 'org.joplinapp.plugins.ToggleSidebars';
const testPluginPath = `${supportDir}/pluginRepo/plugins/${testPluginId}/plugin.jpl`;
const pluginSettings = {
[testPluginId]: defaultPluginSetting(),
};
await service.loadAndRunPlugins([testPluginPath], pluginSettings, { devMode: false, builtIn: false });
// Should be running
expect(service.isPluginLoaded(testPluginId)).toBe(true);
const testDefaultPluginsInfo = {
[testPluginId]: {},
'joplin.plugin.ambrt.backlinksToNote': {},
};
const { pluginPaths } = await getDefaultPluginPathsAndSettings(
testDefaultPluginsDir, testDefaultPluginsInfo, pluginSettings, service,
);
// Should only return plugins that aren't loaded.
expect(pluginPaths).toHaveLength(1);
expect(pluginPaths[0]).toContain('joplin.plugin.ambrt.backlinksToNote');
});
});

View File

@@ -0,0 +1,3 @@
dist/
node_modules/
publish/

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