1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-12-23 23:33:01 +02:00

Compare commits

..

65 Commits

Author SHA1 Message Date
Laurent Cozic
87045a7b60 notarization script 2020-11-29 00:53:17 +00:00
Laurent Cozic
35242b9735 Merge branch 'dev' into mac_notarization 2020-11-29 00:23:13 +00:00
Laurent Cozic
1851b0e7d1 Merge branch 'release-1.4' into dev 2020-11-29 00:22:17 +00:00
Laurent Cozic
0fcb6441de notarize 2020-11-29 00:18:39 +00:00
Laurent Cozic
76c4d99b87 Desktop release v1.4.18 2020-11-28 12:03:29 +00:00
Laurent Cozic
849ef418a6 Desktop: Fixed notifications on macOS 2020-11-28 12:03:06 +00:00
Laurent Cozic
8fbd1ae21a notarization 2020-11-27 20:42:23 +00:00
Laurent Cozic
d733c0e010 Desktop release v1.4.16 2020-11-27 18:19:31 +00:00
Laurent Cozic
a48e5cd4e8 Desktop: Fixed spell checker crash when no language is selected 2020-11-27 18:15:22 +00:00
Laurent Cozic
03942a0073 All: Fix sorting by title in a case insensitive way 2020-11-27 15:16:50 +00:00
Laurent Cozic
0bc53dc063 Merge branch 'release-1.4' into dev 2020-11-27 12:43:40 +00:00
Laurent Cozic
56605beea2 Desktop release v1.4.15 2020-11-27 12:41:24 +00:00
Laurent Cozic
8059d3fbd1 Desktop release v1.4.14 2020-11-27 12:41:12 +00:00
Laurent Cozic
46c38ce0e0 Desktop: Remove support for buggy asar packing as it breaks notifications on macOS. Also make sure only DMG is built for macOS. 2020-11-27 12:40:43 +00:00
Laurent Cozic
dfa928c1f7 Log info 2020-11-27 12:21:59 +00:00
Laurent Cozic
cb696276da Desktop: Fixes #4146: Prevents crash when invalid spell checker language is selected, and provide fallback for invalid language codes 2020-11-27 12:21:34 +00:00
Laurent Cozic
5f80628a4d Desktop: Fixed potential crash when watching note files or resources 2020-11-27 12:19:57 +00:00
Laurent Cozic
b77f868fc8 Log info 2020-11-27 12:03:32 +00:00
Laurent Cozic
6ad9931e43 Desktop: Fixes #4146: Prevents crash when invalid spell checker language is selected, and provide fallback for invalid language codes 2020-11-27 11:12:28 +00:00
Laurent Cozic
011a65f73b Desktop: Fixed potential crash when watching note files or resources 2020-11-27 11:08:42 +00:00
Laurent Cozic
72ccc90ea0 Merge branch 'release-1.4' into dev 2020-11-27 01:16:52 +00:00
Laurent Cozic
f3e6c0da32 Desktop release v1.4.13 2020-11-26 23:32:30 +00:00
Laurent Cozic
9308c3f38c Plugins: Fixed webview postMessage call 2020-11-26 23:31:31 +00:00
Laurent Cozic
c8a7c70838 ios-v10.4.1 2020-11-26 22:17:55 +00:00
Laurent Cozic
40f6dcfb4c Android release 1.4 2020-11-26 19:42:05 +00:00
Laurent Cozic
09785cf366 Tools: Ignored files 2020-11-26 18:15:20 +00:00
Laurent Cozic
7279b508db Tools: Fixed ignore file script 2020-11-26 18:14:49 +00:00
Laurent Cozic
d7996c9707 Merge branch 'release-1.4' into dev 2020-11-26 15:10:18 +00:00
Laurent Cozic
f0432e724a Fix CLI release 2020-11-26 15:09:51 +00:00
Laurent Cozic
2f9bb7b8c0 Doc: Typo 2020-11-26 14:42:50 +00:00
Laurent Cozic
f4b8b5b160 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-11-26 14:42:21 +00:00
Zhang YANG
e2962322be Update zh_CN translations (#4121)
* Update zh_CN.po

* Update zh_CN translations
2020-11-26 14:41:11 +00:00
Mustafa Al-Dailemi
c982e42999 Update da_DK.po (#4117)
Co-authored-by: Mustafa Al-Dailemi <Mustafa-ALD@users.noreply.github.com>
2020-11-26 14:40:30 +00:00
Laurent Cozic
eed52a5cfd Tools: Fixed tests on CI 2020-11-26 14:40:16 +00:00
MichBoi
6272a2eb4f Desktop: Fixes #3917: Fixed numbered list bug in markdown editor (#4116) 2020-11-26 14:34:13 +00:00
Naveen M V
69a4a895d4 All: Fixed basic search when executing a query in Chinese (#4034) 2020-11-26 12:35:04 +00:00
Laurent Cozic
511e4b1da0 Merge branch 'release-1.4' into dev 2020-11-26 12:16:52 +00:00
Laurent Cozic
f22e6f7204 CLI v1.4.7 2020-11-26 12:16:29 +00:00
Laurent Cozic
3d4437037e Tools: trim 2020-11-26 12:15:02 +00:00
Laurent Cozic
d8745597e9 Tools: trim 2020-11-26 12:13:26 +00:00
Laurent Cozic
b279a9693c Tools: Fixed git-changelog error with empty tag 2020-11-26 12:10:56 +00:00
Laurent Cozic
7fa483d27c Doc: Organise community links 2020-11-25 14:50:27 +00:00
Laurent Cozic
9b64c1fbdb Added no-floating-promises eslint rule 2020-11-25 14:40:25 +00:00
Laurent Cozic
a37f84e988 Clipper: Certain tags could be missing from the dropdownlist 2020-11-25 10:27:41 +00:00
Laurent Cozic
96ac3e53e8 Merge branch 'dev' of https://github.com/laurent22/joplin into dev 2020-11-25 09:41:34 +00:00
Laurent Cozic
416a7b36e7 Fix logger type 2020-11-25 09:40:54 +00:00
Laurent Cozic
be4d53db62 Doc: Update Donate page 2020-11-23 17:50:48 +00:00
Laurent Cozic
7154ebbf5c Plugins: Updated types 2020-11-23 17:06:52 +00:00
Laurent Cozic
4d65bfe3f8 Fixed type 2020-11-23 17:05:12 +00:00
Laurent Cozic
0f0c50a178 Desktop release v1.4.12 2020-11-23 16:57:58 +00:00
Laurent Cozic
9a2fd97f3c Merge branch 'dev' of https://github.com/laurent22/joplin into dev 2020-11-23 16:56:09 +00:00
Laurent Cozic
3f2fe79151 All: Partially reverts #3975 (link rendering)
- Reverts the linkify behaviour - URLs will be auto-detected again
- Keeps the new soft-break behaviour

There are still unsolved issues with regard to the linkify option so it
needs further considerations before we change the behaviour.

https://discourse.joplinapp.org/t/12620/18?u=laurent
2020-11-23 16:52:17 +00:00
Laurent Cozic
1ef380d995 Merge branch 'dev' of github.com:laurent22/joplin into dev 2020-11-23 16:40:50 +00:00
Laurent Cozic
c213d5056c Desktop: Fixed resource watching on Windows 2020-11-23 16:38:29 +00:00
Laurent Cozic
62c67cb09f All: Fixed Markdown rendering when code highlighting is disabled 2020-11-23 16:26:34 +00:00
Laurent Cozic
1dd6c7dde5 All: Fix handling of new line escaping when using external edit 2020-11-23 16:25:57 +00:00
Laurent Cozic
86bace70a5 Merge branch 'dev' of https://github.com/laurent22/joplin into dev 2020-11-23 11:52:36 +00:00
Laurent Cozic
ee912b24c7 Plugins: Fixed issue with toolbar button key not being unique 2020-11-23 11:52:20 +00:00
Laurent Cozic
3e65e1539b Desktop, Cli: Fixed importing certain ENEX files that contain invalid dates 2020-11-23 11:23:56 +00:00
Laurent Cozic
4ac2409318 Plugins: Provides selected notes when triggering a command from the note list context menu 2020-11-21 12:35:19 +00:00
Laurent Cozic
d953f6bcab Desktop, Mobile: Fixes #4119: Fixed links imported from ENEX as HTML 2020-11-20 16:04:47 +00:00
Laurent Cozic
e0c2b62a6c Tools: Fixed tests when running them from root 2020-11-20 14:04:02 +00:00
Laurent Cozic
544d879c0b Plugins: Use plugin ID as filename 2020-11-19 23:46:04 +00:00
Laurent Cozic
28f75449d7 Desktop release v1.4.11 2020-11-19 21:02:03 +00:00
Laurent Cozic
fdc84aa6bb Desktop: Upgrade to Electron 10 2020-11-19 21:01:19 +00:00
190 changed files with 10359 additions and 3811 deletions

View File

@@ -58,105 +58,15 @@ plugin_types/
readme/
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
Assets/TinyMCE/JoplinLists/src/main/ts/Main.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/Main.js
Assets/TinyMCE/JoplinLists/src/main/ts/Main.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/Plugin.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/Plugin.js
Assets/TinyMCE/JoplinLists/src/main/ts/Plugin.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/actions/Indendation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/actions/Indendation.js
Assets/TinyMCE/JoplinLists/src/main/ts/actions/Indendation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/actions/ToggleList.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/actions/ToggleList.js
Assets/TinyMCE/JoplinLists/src/main/ts/actions/ToggleList.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Api.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Api.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Api.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Commands.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Commands.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Commands.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Events.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Events.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Events.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Settings.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Settings.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Settings.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Bookmark.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Bookmark.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Bookmark.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Delete.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Delete.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Delete.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/DlIndentation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/DlIndentation.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/DlIndentation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Keyboard.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Keyboard.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Keyboard.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/ListAction.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/ListAction.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/ListAction.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/NodeType.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/NodeType.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/NodeType.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/NormalizeLists.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/NormalizeLists.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/NormalizeLists.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Range.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Range.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Range.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Selection.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Selection.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Selection.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/SplitList.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/SplitList.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/SplitList.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/TextBlock.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/TextBlock.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/TextBlock.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Util.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Util.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Util.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ComposeList.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ComposeList.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ComposeList.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Entry.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Entry.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Entry.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Indentation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Indentation.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Indentation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/JoplinListUtil.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/JoplinListUtil.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/JoplinListUtil.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ListsIndendation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ListsIndendation.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ListsIndendation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/NormalizeEntries.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/NormalizeEntries.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/NormalizeEntries.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ParseLists.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ParseLists.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ParseLists.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Util.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Util.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Util.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/ui/Buttons.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/ui/Buttons.js
Assets/TinyMCE/JoplinLists/src/main/ts/ui/Buttons.js.map
packages/app-cli/app/LinkSelector.d.ts
packages/app-cli/app/LinkSelector.js
packages/app-cli/app/LinkSelector.js.map
packages/app-cli/app/services/plugins/PluginRunner.d.ts
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/services/plugins/PluginRunner.js.map
packages/app-cli/build/LinkSelector.d.ts
packages/app-cli/build/LinkSelector.js
packages/app-cli/build/LinkSelector.js.map
packages/app-cli/build/services/plugins/PluginRunner.d.ts
packages/app-cli/build/services/plugins/PluginRunner.js
packages/app-cli/build/services/plugins/PluginRunner.js.map
packages/app-cli/tests/EnexToMd.d.ts
packages/app-cli/tests/EnexToMd.js
packages/app-cli/tests/EnexToMd.js.map
packages/app-cli/tests/InMemoryCache.d.ts
packages/app-cli/tests/InMemoryCache.js
packages/app-cli/tests/InMemoryCache.js.map
@@ -1351,6 +1261,9 @@ packages/lib/uuid.js.map
packages/lib/versionInfo.d.ts
packages/lib/versionInfo.js
packages/lib/versionInfo.js.map
packages/renderer/HtmlToHtml.d.ts
packages/renderer/HtmlToHtml.js
packages/renderer/HtmlToHtml.js.map
packages/renderer/InMemoryCache.d.ts
packages/renderer/InMemoryCache.js
packages/renderer/InMemoryCache.js.map
@@ -1360,6 +1273,12 @@ packages/renderer/MarkupToHtml.js.map
packages/renderer/MdToHtml.d.ts
packages/renderer/MdToHtml.js
packages/renderer/MdToHtml.js.map
packages/renderer/MdToHtml/linkReplacement.d.ts
packages/renderer/MdToHtml/linkReplacement.js
packages/renderer/MdToHtml/linkReplacement.js.map
packages/renderer/MdToHtml/linkReplacement.test.d.ts
packages/renderer/MdToHtml/linkReplacement.test.js
packages/renderer/MdToHtml/linkReplacement.test.js.map
packages/renderer/MdToHtml/rules/checkbox.d.ts
packages/renderer/MdToHtml/rules/checkbox.js
packages/renderer/MdToHtml/rules/checkbox.js.map
@@ -1393,6 +1312,9 @@ packages/renderer/MdToHtml/rules/mermaid.js.map
packages/renderer/MdToHtml/rules/sanitize_html.d.ts
packages/renderer/MdToHtml/rules/sanitize_html.js
packages/renderer/MdToHtml/rules/sanitize_html.js.map
packages/renderer/htmlUtils.d.ts
packages/renderer/htmlUtils.js
packages/renderer/htmlUtils.js.map
packages/renderer/index.d.ts
packages/renderer/index.js
packages/renderer/index.js.map
@@ -1402,4 +1324,7 @@ packages/renderer/noteStyle.js.map
packages/renderer/pathUtils.d.ts
packages/renderer/pathUtils.js
packages/renderer/pathUtils.js.map
packages/renderer/utils.d.ts
packages/renderer/utils.js
packages/renderer/utils.js.map
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD

View File

@@ -126,6 +126,10 @@ module.exports = {
{
// enable the rule specifically for TypeScript files
'files': ['*.ts', '*.tsx'],
'parserOptions': {
// Required for @typescript-eslint/no-floating-promises
'project': './tsconfig.eslint.json',
},
'rules': {
// Warn only because it would make it difficult to convert JS classes to TypeScript, unless we
// make everything public which is not great. New code however should specify member accessibility.
@@ -152,6 +156,7 @@ module.exports = {
'requireLast': false,
},
}],
'@typescript-eslint/no-floating-promises': ['error'],
},
},
],

111
.gitignore vendored
View File

@@ -50,105 +50,15 @@ packages/tools/github_oauth_token.txt
lerna-debug.log
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
Assets/TinyMCE/JoplinLists/src/main/ts/Main.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/Main.js
Assets/TinyMCE/JoplinLists/src/main/ts/Main.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/Plugin.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/Plugin.js
Assets/TinyMCE/JoplinLists/src/main/ts/Plugin.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/actions/Indendation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/actions/Indendation.js
Assets/TinyMCE/JoplinLists/src/main/ts/actions/Indendation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/actions/ToggleList.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/actions/ToggleList.js
Assets/TinyMCE/JoplinLists/src/main/ts/actions/ToggleList.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Api.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Api.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Api.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Commands.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Commands.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Commands.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Events.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Events.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Events.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/api/Settings.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/api/Settings.js
Assets/TinyMCE/JoplinLists/src/main/ts/api/Settings.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Bookmark.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Bookmark.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Bookmark.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Delete.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Delete.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Delete.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/DlIndentation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/DlIndentation.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/DlIndentation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Keyboard.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Keyboard.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Keyboard.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/ListAction.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/ListAction.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/ListAction.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/NodeType.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/NodeType.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/NodeType.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/NormalizeLists.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/NormalizeLists.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/NormalizeLists.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Range.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Range.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Range.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Selection.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Selection.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Selection.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/SplitList.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/SplitList.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/SplitList.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/TextBlock.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/TextBlock.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/TextBlock.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/core/Util.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/core/Util.js
Assets/TinyMCE/JoplinLists/src/main/ts/core/Util.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ComposeList.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ComposeList.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ComposeList.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Entry.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Entry.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Entry.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Indentation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Indentation.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Indentation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/JoplinListUtil.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/JoplinListUtil.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/JoplinListUtil.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ListsIndendation.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ListsIndendation.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ListsIndendation.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/NormalizeEntries.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/NormalizeEntries.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/NormalizeEntries.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ParseLists.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ParseLists.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/ParseLists.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Util.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Util.js
Assets/TinyMCE/JoplinLists/src/main/ts/listModel/Util.js.map
Assets/TinyMCE/JoplinLists/src/main/ts/ui/Buttons.d.ts
Assets/TinyMCE/JoplinLists/src/main/ts/ui/Buttons.js
Assets/TinyMCE/JoplinLists/src/main/ts/ui/Buttons.js.map
packages/app-cli/app/LinkSelector.d.ts
packages/app-cli/app/LinkSelector.js
packages/app-cli/app/LinkSelector.js.map
packages/app-cli/app/services/plugins/PluginRunner.d.ts
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/services/plugins/PluginRunner.js.map
packages/app-cli/build/LinkSelector.d.ts
packages/app-cli/build/LinkSelector.js
packages/app-cli/build/LinkSelector.js.map
packages/app-cli/build/services/plugins/PluginRunner.d.ts
packages/app-cli/build/services/plugins/PluginRunner.js
packages/app-cli/build/services/plugins/PluginRunner.js.map
packages/app-cli/tests/EnexToMd.d.ts
packages/app-cli/tests/EnexToMd.js
packages/app-cli/tests/EnexToMd.js.map
packages/app-cli/tests/InMemoryCache.d.ts
packages/app-cli/tests/InMemoryCache.js
packages/app-cli/tests/InMemoryCache.js.map
@@ -1343,6 +1253,9 @@ packages/lib/uuid.js.map
packages/lib/versionInfo.d.ts
packages/lib/versionInfo.js
packages/lib/versionInfo.js.map
packages/renderer/HtmlToHtml.d.ts
packages/renderer/HtmlToHtml.js
packages/renderer/HtmlToHtml.js.map
packages/renderer/InMemoryCache.d.ts
packages/renderer/InMemoryCache.js
packages/renderer/InMemoryCache.js.map
@@ -1352,6 +1265,12 @@ packages/renderer/MarkupToHtml.js.map
packages/renderer/MdToHtml.d.ts
packages/renderer/MdToHtml.js
packages/renderer/MdToHtml.js.map
packages/renderer/MdToHtml/linkReplacement.d.ts
packages/renderer/MdToHtml/linkReplacement.js
packages/renderer/MdToHtml/linkReplacement.js.map
packages/renderer/MdToHtml/linkReplacement.test.d.ts
packages/renderer/MdToHtml/linkReplacement.test.js
packages/renderer/MdToHtml/linkReplacement.test.js.map
packages/renderer/MdToHtml/rules/checkbox.d.ts
packages/renderer/MdToHtml/rules/checkbox.js
packages/renderer/MdToHtml/rules/checkbox.js.map
@@ -1385,6 +1304,9 @@ packages/renderer/MdToHtml/rules/mermaid.js.map
packages/renderer/MdToHtml/rules/sanitize_html.d.ts
packages/renderer/MdToHtml/rules/sanitize_html.js
packages/renderer/MdToHtml/rules/sanitize_html.js.map
packages/renderer/htmlUtils.d.ts
packages/renderer/htmlUtils.js
packages/renderer/htmlUtils.js.map
packages/renderer/index.d.ts
packages/renderer/index.js
packages/renderer/index.js.map
@@ -1394,4 +1316,7 @@ packages/renderer/noteStyle.js.map
packages/renderer/pathUtils.d.ts
packages/renderer/pathUtils.js
packages/renderer/pathUtils.js.map
packages/renderer/utils.d.ts
packages/renderer/utils.js
packages/renderer/utils.js.map
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD

View File

@@ -91,7 +91,7 @@ Note that you should most likely always specify a scope because otherwise it wil
## TypeScript
The application was originally written JavaScript, however it has slowly been migrated to [TypeScript](https://www.typescriptlang.org/). New classes and files should be written in TypeScript. All compiled files are generated next to the .ts or .tsx file. So for example, if there's a file "lib/MyClass.ts", there will be a generated "lib/MyClass.js" next to it. It is implemented that way as it requires minimal changes to integrate TypeScript in the existing JavaScript code base.
The application was originally written in JavaScript, however it has slowly been migrated to [TypeScript](https://www.typescriptlang.org/). New classes and files should be written in TypeScript. All compiled files are generated next to the .ts or .tsx file. So for example, if there's a file "lib/MyClass.ts", there will be a generated "lib/MyClass.js" next to it. It is implemented that way as it requires minimal changes to integrate TypeScript in the existing JavaScript code base.
## Hot reload

View File

@@ -28,7 +28,7 @@ Linux | <a href='https://github.com/laurent22/joplin/releases/download/
Operating System | Download | Alt. Download
-----------------|----------|----------------
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplinapp.org/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.3.13/joplin-v1.3.13.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.3.13/joplin-v1.3.13-32bit.apk)
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplinapp.org/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.4.11/joplin-v1.4.11.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.4.11/joplin-v1.4.11-32bit.apk)
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://joplinapp.org/images/BadgeIOS.png'/></a> | -
## Terminal application
@@ -402,13 +402,14 @@ Please see the [donation page](https://github.com/laurent22/joplin/blob/dev/read
# Community
- For general discussion about Joplin, user support, software development questions, and to discuss new features, go to the [Joplin Forum](https://discourse.joplinapp.org/). It is possible to login with your GitHub account.
- Also see here for information about [the latest releases and general news](https://discourse.joplinapp.org/c/news).
- For bug reports go to the [GitHub Issue Tracker](https://github.com/laurent22/joplin/issues). Please follow the template accordingly.
- Feature requests must not be opened on GitHub unless they have been discussed and accepted on the forum.
- The latest news are posted [on the Patreon page](https://www.patreon.com/joplin).
- You can also follow us on <a rel="me" href="https://mastodon.social/@joplinapp">the Mastodon feed</a> or [the Twitter feed](https://twitter.com/joplinapp).
- You can join the live community on [the JoplinApp discord server](https://discordapp.com/invite/d2HMPwE) to get help with Joplin or to discuss anything Joplin related.
Name | Description
--- | ---
[Support Forum](https://discourse.joplinapp.org/) | This is the main place for general discussion about Joplin, user support, software development questions, and to discuss new features. Also where the latest beta versions are released and discussed.
[Sub-reddit](https://www.reddit.com/r/joplinapp/) | Also a good place to get help
[Discord server](https://discordapp.com/invite/d2HMPwE) | Our chat server
[Patreon page](https://www.patreon.com/joplin) |The latest news are often posted there
[Mastodon feed](https://mastodon.social/@joplinapp) | Follow us on Mastodon
[Twitter feed](https://twitter.com/joplinapp) | Follow us on Twitter
# Contributing

View File

@@ -30,11 +30,11 @@ module.exports = {
],
testPathIgnorePatterns: [
'/node_modules/',
'/tests\\/support/',
'/build/',
'test-utils.js',
'file_api_driver.js',
'<rootDir>/node_modules/',
'<rootDir>/tests/support/',
'<rootDir>/build/',
'<rootDir>/tests/test-utils.js',
'<rootDir>/tests/file_api_driver.js',
'<rootDir>/tests/tmp/',
],
@@ -52,5 +52,5 @@ module.exports = {
],
testEnvironment: 'node',
setupFilesAfterEnv: ['./jest.setup.js'],
setupFilesAfterEnv: [`${__dirname}/jest.setup.js`],
};

View File

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

View File

@@ -31,7 +31,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.4.3",
"version": "1.4.9",
"bin": {
"joplin": "./main.js"
},

View File

@@ -1,67 +0,0 @@
/* eslint-disable no-unused-vars */
const os = require('os');
const time = require('@joplin/lib/time').default;
const { filename } = require('@joplin/lib/path-utils');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder.js');
const Note = require('@joplin/lib/models/Note.js');
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
describe('EnexToMd', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should convert from Enex to Markdown', asyncTest(async () => {
const basePath = `${__dirname}/enex_to_md`;
const files = await shim.fsDriver().readDirStats(basePath);
for (let i = 0; i < files.length; i++) {
const htmlFilename = files[i].path;
if (htmlFilename.indexOf('.html') < 0) continue;
const htmlPath = `${basePath}/${htmlFilename}`;
const mdPath = `${basePath}/${filename(htmlFilename)}.md`;
// if (htmlFilename !== 'multiline_inner_text.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
let expectedMd = await shim.fsDriver().readFile(mdPath);
let actualMd = await enexXmlToMd(`<div>${html}</div>`, []);
if (os.EOL === '\r\n') {
expectedMd = expectedMd.replace(/\r\n/g, '\n');
actualMd = actualMd.replace(/\r\n/g, '\n');
}
if (actualMd !== expectedMd) {
console.info('');
console.info(`Error converting file: ${htmlFilename}`);
console.info('--------------------------------- Got:');
console.info(actualMd.split('\n'));
console.info('--------------------------------- Expected:');
console.info(expectedMd.split('\n'));
console.info('--------------------------------------------');
console.info('');
expect(false).toBe(true);
// return;
} else {
expect(true).toBe(true);
}
}
}));
});

View File

@@ -0,0 +1,99 @@
import { NoteEntity, ResourceEntity, TagEntity } from '@joplin/lib/services/database/types';
import shim from '@joplin/lib/shim';
const fs = require('fs-extra');
const os = require('os');
const { filename } = require('@joplin/lib/path-utils');
const { setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
const { importEnex } = require('@joplin/lib/import-enex');
const Note = require('@joplin/lib/models/Note');
const Tag = require('@joplin/lib/models/Tag');
const Resource = require('@joplin/lib/models/Resource');
const enexSampleBaseDir = `${__dirname}/enex_to_md`;
describe('EnexToMd', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should convert ENEX content to Markdown', async () => {
const files = await shim.fsDriver().readDirStats(enexSampleBaseDir);
for (let i = 0; i < files.length; i++) {
const htmlFilename = files[i].path;
if (htmlFilename.indexOf('.html') < 0) continue;
const htmlPath = `${enexSampleBaseDir}/${htmlFilename}`;
const mdPath = `${enexSampleBaseDir}/${filename(htmlFilename)}.md`;
// if (htmlFilename !== 'multiline_inner_text.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
let expectedMd = await shim.fsDriver().readFile(mdPath);
let actualMd = await enexXmlToMd(`<div>${html}</div>`, []);
if (os.EOL === '\r\n') {
expectedMd = expectedMd.replace(/\r\n/g, '\n');
actualMd = actualMd.replace(/\r\n/g, '\n');
}
if (actualMd !== expectedMd) {
console.info('');
console.info(`Error converting file: ${htmlFilename}`);
console.info('--------------------------------- Got:');
console.info(actualMd.split('\n'));
console.info('--------------------------------- Expected:');
console.info(expectedMd.split('\n'));
console.info('--------------------------------------------');
console.info('');
expect(false).toBe(true);
// return;
} else {
expect(true).toBe(true);
}
}
});
it('should import ENEX metadata', async () => {
const filePath = `${enexSampleBaseDir}/sample-enex.xml`;
await importEnex('', filePath);
const note: NoteEntity = (await Note.all())[0];
expect(note.title).toBe('Test Note for Export');
expect(note.body).toBe([
' Hello, World.',
'',
'![snapshot-DAE9FC15-88E3-46CF-B744-DA9B1B56EB57.jpg](:/3d0f4d01abc02cf8c4dc1c796df8c4b2)',
].join('\n'));
expect(note.created_time).toBe(1375217524000);
expect(note.updated_time).toBe(1376560800000);
expect(note.latitude).toBe('33.88394692');
expect(note.longitude).toBe('-117.91913551');
expect(note.altitude).toBe('96.0000');
expect(note.author).toBe('Brett Kelly');
const tag: TagEntity = (await Tag.tagsByNoteId(note.id))[0];
expect(tag.title).toBe('fake-tag');
const resource: ResourceEntity = (await Resource.all())[0];
expect(resource.id).toBe('3d0f4d01abc02cf8c4dc1c796df8c4b2');
const stat = await fs.stat(Resource.fullPath(resource));
expect(stat.size).toBe(277);
});
it('should handle invalid dates', async () => {
const filePath = `${enexSampleBaseDir}/invalid_date.enex`;
await importEnex('', filePath);
const note: NoteEntity = (await Note.all())[0];
expect(note.created_time).toBe(1521822724000); // 20180323T163204Z
expect(note.updated_time).toBe(1521822724000); // Because this date was invalid, it is set to the created time instead
});
});

View File

@@ -9,7 +9,7 @@ const Folder = require('@joplin/lib/models/Folder.js');
const Note = require('@joplin/lib/models/Note.js');
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
const HtmlToHtml = require('@joplin/renderer/HtmlToHtml');
const HtmlToHtml = require('@joplin/renderer/HtmlToHtml').default;
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
process.on('unhandledRejection', (reason, p) => {

View File

@@ -147,27 +147,27 @@ describe('MdToHtml', function() {
expect(result.html.trim()).toBe('<div id="rendered-md"><p>just <strong>testing</strong></p>\n</div>');
}));
it('should render links correctly', asyncTest(async () => {
const mdToHtml = newTestMdToHtml();
// it('should render links correctly', asyncTest(async () => {
// const mdToHtml = newTestMdToHtml();
const testCases = [
// None of these should result in a link
['https://example.com', 'https://example.com'],
['file://C:\\AUTOEXEC.BAT', 'file://C:\\AUTOEXEC.BAT'],
['example.com', 'example.com'],
['oo.ps', 'oo.ps'],
['test@example.com', 'test@example.com'],
// const testCases = [
// // None of these should result in a link
// ['https://example.com', 'https://example.com'],
// ['file://C:\\AUTOEXEC.BAT', 'file://C:\\AUTOEXEC.BAT'],
// ['example.com', 'example.com'],
// ['oo.ps', 'oo.ps'],
// ['test@example.com', 'test@example.com'],
// Those should be converted to links
['<https://example.com>', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>https://example.com</a>'],
['[ok](https://example.com)', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>ok</a>'],
];
// // Those should be converted to links
// ['<https://example.com>', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>https://example.com</a>'],
// ['[ok](https://example.com)', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>ok</a>'],
// ];
for (const testCase of testCases) {
const [input, expected] = testCase;
const actual = await mdToHtml.render(input, null, { bodyOnly: true, plainResourceRendering: true });
expect(actual.html).toBe(expected);
}
}));
// for (const testCase of testCases) {
// const [input, expected] = testCase;
// const actual = await mdToHtml.render(input, null, { bodyOnly: true, plainResourceRendering: true });
// expect(actual.html).toBe(expected);
// }
// }));
});

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">
<en-export export-date="20201223T053642Z" application="Evernote" version="10.4.3">
<note>
<title>Fruit Tree Assessment</title>
<created>20180323T163204Z</created>
<updated>10101T000000Z</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>Fruit Tree</en-note> ]]>
</content>
</note>
</en-export>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">
<en-export export-date="20130730T205637Z" application="Evernote" version="Evernote Mac">
<note>
<title>Test Note for Export</title>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
Hello, World.
<div>
<br/>
</div>
<div>
<en-media alt="" type="image/jpeg" hash="dd7b6d285d09ec054e8cd6a3814ce093"/>
</div>
<div>
<br/>
</div>
</en-note>
]]>
</content>
<created>20130730T205204Z</created>
<updated>20130815T100000Z</updated>
<tag>fake-tag</tag>
<note-attributes>
<latitude>33.88394692352314</latitude>
<longitude>-117.9191355110099</longitude>
<altitude>96</altitude>
<author>Brett Kelly</author>
</note-attributes>
<resource>
<data encoding="base64">/9j/4AAQSkZJRgABAQAAAQABAAD/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdCIFhZ
WiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLUhQ
kfeIGT/+uufk8DpM0gyVjGfmzkgetesnUoTHJ+5Cxn86zmv4/wB75EW+QHAPUH/P9Ky+s1rtrr/wfvOm
dBSamnq/xPKp/hpLKmS7x4OBjgn6elee6v4OuLJirRSHb/FtyG9s9u1fR0+oTiIRvGq7W4bpisfUGk1C
GVWtkIyM57n1rfDY+uqigtU76ffZkUsA6iajHZ6v/P8A4B//2Q==</data>
<mime>image/jpeg</mime>
<width>1280</width>
<height>720</height>
<resource-attributes>
<file-name>snapshot-DAE9FC15-88E3-46CF-B744-DA9B1B56EB57.jpg</file-name>
</resource-attributes>
</resource>
</note>
</en-export>

View File

@@ -105,7 +105,11 @@ describe('models_BaseItem', function() {
}));
it('should serialize and unserialize properties that contain new lines', asyncTest(async () => {
const note = await Note.save({ title: 'note', source_url: '\nhttps://joplinapp.org/\n' });
const sourceUrl = `
https://joplinapp.org/ \\n
`;
const note = await Note.save({ title: 'note', source_url: sourceUrl });
const noteBefore = await Note.load(note.id);
const serialized = await Note.serialize(noteBefore);
@@ -113,4 +117,18 @@ describe('models_BaseItem', function() {
expect(noteAfter).toEqual(noteBefore);
}));
it('should not serialize the note title and body', asyncTest(async () => {
const note = await Note.save({ title: 'my note', body: `one line
two line
three line \\n no escape` });
const noteBefore = await Note.load(note.id);
const serialized = await Note.serialize(noteBefore);
expect(serialized.indexOf(`my note
one line
two line
three line \\n no escape`)).toBe(0);
}));
});

View File

@@ -3,7 +3,9 @@ import PluginService 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';
import Setting from '@joplin/lib/models/Setting';
const fs = require('fs-extra');
const { asyncTest, expectNotThrow, setupDatabaseAndSynchronizer, switchClient, expectThrow, createTempDir } = require('./test-utils.js');
const Note = require('@joplin/lib/models/Note');
const Folder = require('@joplin/lib/models/Folder');
@@ -260,4 +262,23 @@ describe('services_PluginService', function() {
}
}));
it('should install a plugin', asyncTest(async () => {
const service = newPluginService();
const pluginPath = `${testPluginDir}/jpl_test/org.joplinapp.FirstJplPlugin.jpl`;
await service.installPlugin(pluginPath);
const installedPluginPath = `${Setting.value('pluginDir')}/org.joplinapp.FirstJplPlugin.jpl`;
expect(await fs.existsSync(installedPluginPath)).toBe(true);
}));
it('should rename the plugin archive to the right name', asyncTest(async () => {
const tempDir = await createTempDir();
const service = newPluginService();
const pluginPath = `${testPluginDir}/jpl_test/org.joplinapp.FirstJplPlugin.jpl`;
const tempPath = `${tempDir}/something.jpl`;
await shim.fsDriver().copy(pluginPath, tempPath);
const installedPluginPath = `${Setting.value('pluginDir')}/org.joplinapp.FirstJplPlugin.jpl`;
await service.installPlugin(tempPath);
expect(await fs.existsSync(installedPluginPath)).toBe(true);
}));
});

View File

@@ -447,7 +447,7 @@ describe('services_SearchEngine', function() {
expect((await engine.search('title:bla 我是')).length).toBe(0);
// For non-alpha char, only the first field is looked at, the following ones are ignored
expect((await engine.search('title:你好 title:hello')).length).toBe(1);
// expect((await engine.search('title:你好 title:hello')).length).toBe(1);
}));
it('should parse normal query strings', asyncTest(async () => {

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -21,6 +21,20 @@ joplin.plugins.register({
},
});
await joplin.commands.register({
name: 'contextMenuCommandExample',
label: 'My Context Menu command',
execute: async (noteIds:string[]) => {
const notes = [];
for (const noteId of noteIds) {
notes.push(await joplin.data.get(['notes', noteId]));
}
const noteTitles = notes.map((note:any) => note.title);
alert('The following notes will be processed:\n\n' + noteTitles.join(', '));
},
});
// Commands that return a result and take argument can only be used
// programmatically, so it's not necessary to set a label and icon.
await joplin.commands.register({
@@ -40,6 +54,8 @@ joplin.plugins.register({
await joplin.views.menuItems.create('myMenuItem1', 'testCommand1', MenuItemLocation.Tools, { accelerator: 'CmdOrCtrl+Alt+Shift+B' });
await joplin.views.menuItems.create('myMenuItem2', 'testCommand2', MenuItemLocation.Tools);
await joplin.views.menuItems.create('contextMenuItem1', 'contextMenuCommandExample', MenuItemLocation.NoteListContextMenu);
console.info('Running command with arguments...');
const result = await joplin.commands.execute('commandWithResult', 'abcd', 123);
console.info('Result was: ' + result);

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -23,4 +23,4 @@
"dependencies": {
"uslug": "^1.0.4"
}
}
}

View File

@@ -1,6 +1,7 @@
document.addEventListener('click', event => {
const element = event.target;
if (element.className === 'toc-item-link') {
console.debug('TOC Plugin Webview: Sending scrollToHash message', element.dataset.slug);
webviewApi.postMessage({
name: 'scrollToHash',
hash: element.dataset.slug,

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,13 +1,12 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,7 +7,6 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -32,7 +31,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
constructor(implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,13 +1,11 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
constructor(plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"keywords": {},
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -23,4 +23,4 @@
"dependencies": {
"left-pad": "^1.3.0"
}
}
}

View File

@@ -16,6 +16,13 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -38,6 +45,8 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -216,6 +216,7 @@ async function switchClient(id, options = null) {
await Setting.reset();
Setting.setConstant('resourceDirName', resourceDirName(id));
Setting.setConstant('resourceDir', resourceDir(id));
Setting.setConstant('pluginDir', pluginDir(id));
await loadKeychainServiceAndSettings(options.keychainEnabled ? KeychainServiceDriver : KeychainServiceDriverDummy);
@@ -294,6 +295,11 @@ function resourceDir(id = null) {
return `${__dirname}/data/${resourceDirName(id)}`;
}
function pluginDir(id = null) {
if (id === null) id = currentClient_;
return `${__dirname}/data/plugins-${id}`;
}
async function setupDatabaseAndSynchronizer(id = null, options = null) {
if (id === null) id = currentClient_;
@@ -307,6 +313,9 @@ async function setupDatabaseAndSynchronizer(id = null, options = null) {
await fs.remove(resourceDir(id));
await fs.mkdirp(resourceDir(id), 0o755);
await fs.remove(pluginDir(id));
await fs.mkdirp(pluginDir(id), 0o755);
if (!synchronizers_[id]) {
const SyncTargetClass = SyncTargetRegistry.classById(syncTargetId_);
const syncTarget = new SyncTargetClass(db(id));
@@ -727,7 +736,7 @@ class TestApp extends BaseApplication {
}
async profileDir() {
return await Setting.value('profileDir');
return Setting.value('profileDir');
}
async destroy() {

View File

@@ -150,8 +150,16 @@ class Bridge {
const folders = await this.folderTree();
this.dispatch({ type: 'FOLDERS_SET', folders: folders.items ? folders.items : folders });
const tags = await this.clipperApiExec('GET', 'tags');
this.dispatch({ type: 'TAGS_SET', tags: tags.items ? tags.items : tags });
let tags = [];
for (let page = 1; page < 10000; page++) {
const result = await this.clipperApiExec('GET', 'tags', { page: page, order_by: 'title', order_dir: 'ASC' });
const resultTags = result.items ? result.items : result;
const hasMore = ('has_more' in result) && result.has_more;
tags = tags.concat(resultTags);
if (!hasMore) break;
}
this.dispatch({ type: 'TAGS_SET', tags: tags });
bridge().restoreState();
return;

View File

@@ -156,7 +156,7 @@ export default class InteropServiceHelper {
if (Array.isArray(path)) path = path[0];
CommandService.instance().execute('showModalMessage', _('Exporting to "%s" as "%s" format. Please wait...', path, module.format));
void CommandService.instance().execute('showModalMessage', _('Exporting to "%s" as "%s" format. Please wait...', path, module.format));
const exportOptions: ExportOptions = {};
exportOptions.path = path;
@@ -177,7 +177,7 @@ export default class InteropServiceHelper {
bridge().showErrorMessageBox(_('Could not export notes: %s', error.message));
}
CommandService.instance().execute('hideModalMessage');
void CommandService.instance().execute('hideModalMessage');
}
}

View File

@@ -424,7 +424,7 @@ class Application extends BaseApplication {
const contextMenu = Menu.buildFromTemplate([
{ label: _('Open %s', app.electronApp().name), click: () => { app.window().show(); } },
{ type: 'separator' },
{ label: _('Quit'), click: () => { app.quit(); } },
{ label: _('Quit'), click: () => { void app.quit(); } },
]);
app.createTray(contextMenu);
}
@@ -664,7 +664,7 @@ class Application extends BaseApplication {
this.updateTray();
shim.setTimeout(() => {
AlarmService.garbageCollect();
void AlarmService.garbageCollect();
}, 1000 * 60 * 60);
if (Setting.value('startMinimized') && Setting.value('showTrayIcon')) {
@@ -676,12 +676,12 @@ class Application extends BaseApplication {
ResourceService.runInBackground();
if (Setting.value('env') === 'dev') {
AlarmService.updateAllNotifications();
void AlarmService.updateAllNotifications();
} else {
reg.scheduleSync(1000).then(() => {
// Wait for the first sync before updating the notifications, since synchronisation
// might change the notifications.
AlarmService.updateAllNotifications();
void AlarmService.updateAllNotifications();
DecryptionWorker.instance().scheduleStart();
});

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>

View File

@@ -11,7 +11,7 @@ export const declaration: CommandDeclaration = {
export const runtime = (): CommandRuntime => {
return {
execute: async () => {
bridge().openItem(Setting.value('profileDir'));
void bridge().openItem(Setting.value('profileDir'));
},
};
};

View File

@@ -18,7 +18,7 @@ export const runtime = (): CommandRuntime => {
try {
const note = await Note.load(noteId);
ExternalEditWatcher.instance().openAndWatch(note);
void ExternalEditWatcher.instance().openAndWatch(note);
} catch (error) {
bridge().showErrorMessageBox(_('Error opening note in editor: %s', error.message));
}

View File

@@ -13,7 +13,7 @@ export const runtime = (): CommandRuntime => {
return {
execute: async (context: CommandContext, noteId: string = null) => {
noteId = noteId || stateUtils.selectedNoteId(context.state);
ExternalEditWatcher.instance().stopWatching(noteId);
void ExternalEditWatcher.instance().stopWatching(noteId);
},
enabledCondition: 'oneNoteSelected',
};

View File

@@ -17,9 +17,9 @@ export const runtime = (): CommandRuntime => {
if (!noteId) return;
if (context.state.watchedNoteFiles.includes(noteId)) {
CommandService.instance().execute('stopExternalEditing', noteId);
void CommandService.instance().execute('stopExternalEditing', noteId);
} else {
CommandService.instance().execute('startExternalEditing', noteId);
void CommandService.instance().execute('startExternalEditing', noteId);
}
},
enabledCondition: 'oneNoteSelected',

View File

@@ -696,7 +696,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
const needRestartComp: any = this.state.needRestart ? (
<div style={{ ...theme.textStyle, padding: 10, paddingLeft: 24, backgroundColor: theme.warningBackgroundColor, color: theme.color }}>
{this.restartMessage()}
<a style={{ ...theme.urlStyle, marginLeft: 10 }} href="#" onClick={() => { this.restartApp(); }}>{_('Restart now')}</a>
<a style={{ ...theme.urlStyle, marginLeft: 10 }} href="#" onClick={() => { void this.restartApp(); }}>{_('Restart now')}</a>
</div>
) : null;

View File

@@ -86,7 +86,7 @@ const useKeymap = (): [
}
}
saveKeymap();
void saveKeymap();
}, [keymapItems, mustSave]);
return [keymapItems, keymapError, overrideKeymapItems, setAccelerator, resetAccelerator];

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