You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2026-01-14 00:29:38 +02:00
Compare commits
85 Commits
plugin-gen
...
mac_notari
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87045a7b60 | ||
|
|
35242b9735 | ||
|
|
1851b0e7d1 | ||
|
|
0fcb6441de | ||
|
|
76c4d99b87 | ||
|
|
849ef418a6 | ||
|
|
8fbd1ae21a | ||
|
|
d733c0e010 | ||
|
|
a48e5cd4e8 | ||
|
|
03942a0073 | ||
|
|
0bc53dc063 | ||
|
|
56605beea2 | ||
|
|
8059d3fbd1 | ||
|
|
46c38ce0e0 | ||
|
|
dfa928c1f7 | ||
|
|
cb696276da | ||
|
|
5f80628a4d | ||
|
|
b77f868fc8 | ||
|
|
6ad9931e43 | ||
|
|
011a65f73b | ||
|
|
72ccc90ea0 | ||
|
|
f3e6c0da32 | ||
|
|
9308c3f38c | ||
|
|
c8a7c70838 | ||
|
|
40f6dcfb4c | ||
|
|
09785cf366 | ||
|
|
7279b508db | ||
|
|
d7996c9707 | ||
|
|
f0432e724a | ||
|
|
2f9bb7b8c0 | ||
|
|
f4b8b5b160 | ||
|
|
e2962322be | ||
|
|
c982e42999 | ||
|
|
eed52a5cfd | ||
|
|
6272a2eb4f | ||
|
|
69a4a895d4 | ||
|
|
511e4b1da0 | ||
|
|
f22e6f7204 | ||
|
|
3d4437037e | ||
|
|
d8745597e9 | ||
|
|
b279a9693c | ||
|
|
7fa483d27c | ||
|
|
9b64c1fbdb | ||
|
|
a37f84e988 | ||
|
|
96ac3e53e8 | ||
|
|
416a7b36e7 | ||
|
|
be4d53db62 | ||
|
|
7154ebbf5c | ||
|
|
4d65bfe3f8 | ||
|
|
0f0c50a178 | ||
|
|
9a2fd97f3c | ||
|
|
3f2fe79151 | ||
|
|
1ef380d995 | ||
|
|
c213d5056c | ||
|
|
62c67cb09f | ||
|
|
1dd6c7dde5 | ||
|
|
86bace70a5 | ||
|
|
ee912b24c7 | ||
|
|
3e65e1539b | ||
|
|
4ac2409318 | ||
|
|
d953f6bcab | ||
|
|
e0c2b62a6c | ||
|
|
544d879c0b | ||
|
|
28f75449d7 | ||
|
|
fdc84aa6bb | ||
|
|
592b9d95c6 | ||
|
|
4abdab5cdb | ||
|
|
858508bfa9 | ||
|
|
116413e78d | ||
|
|
031a26116c | ||
|
|
65962e26ce | ||
|
|
30913a5d58 | ||
|
|
61618fb37c | ||
|
|
a40ab434ca | ||
|
|
dbbd930f81 | ||
|
|
ff3ae3860e | ||
|
|
e1c4d1a417 | ||
|
|
e1180a1d84 | ||
|
|
e57444dc32 | ||
|
|
f36019c94d | ||
|
|
c67c8cefdf | ||
|
|
a9a69b046f | ||
|
|
98a75e67d8 | ||
|
|
7188eb9db4 | ||
|
|
52b13f6d56 |
129
.eslintignore
129
.eslintignore
@@ -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
|
||||
@@ -241,6 +151,15 @@ packages/app-cli/tests/support/plugins/events/api/types.js.map
|
||||
packages/app-cli/tests/support/plugins/events/src/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/events/src/index.js
|
||||
packages/app-cli/tests/support/plugins/events/src/index.js.map
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/index.js
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/index.js.map
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/types.d.ts
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/types.js
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/types.js.map
|
||||
packages/app-cli/tests/support/plugins/jpl_test/src/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/jpl_test/src/index.js
|
||||
packages/app-cli/tests/support/plugins/jpl_test/src/index.js.map
|
||||
packages/app-cli/tests/support/plugins/json_export/api/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/json_export/api/index.js
|
||||
packages/app-cli/tests/support/plugins/json_export/api/index.js.map
|
||||
@@ -367,6 +286,9 @@ packages/app-desktop/gui/ConfigScreen/ConfigScreen.js.map
|
||||
packages/app-desktop/gui/ConfigScreen/SideBar.d.ts
|
||||
packages/app-desktop/gui/ConfigScreen/SideBar.js
|
||||
packages/app-desktop/gui/ConfigScreen/SideBar.js.map
|
||||
packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.d.ts
|
||||
packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js.map
|
||||
packages/app-desktop/gui/DropboxLoginScreen.d.ts
|
||||
packages/app-desktop/gui/DropboxLoginScreen.js
|
||||
packages/app-desktop/gui/DropboxLoginScreen.js.map
|
||||
@@ -730,6 +652,9 @@ packages/app-desktop/gui/ToolbarButton/ToolbarButton.js.map
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.d.ts
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.js
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.js.map
|
||||
packages/app-desktop/gui/dialogs.d.ts
|
||||
packages/app-desktop/gui/dialogs.js
|
||||
packages/app-desktop/gui/dialogs.js.map
|
||||
packages/app-desktop/gui/hooks/useEffectDebugger.d.ts
|
||||
packages/app-desktop/gui/hooks/useEffectDebugger.js
|
||||
packages/app-desktop/gui/hooks/useEffectDebugger.js.map
|
||||
@@ -742,6 +667,9 @@ packages/app-desktop/gui/hooks/usePrevious.js.map
|
||||
packages/app-desktop/gui/hooks/usePropsDebugger.d.ts
|
||||
packages/app-desktop/gui/hooks/usePropsDebugger.js
|
||||
packages/app-desktop/gui/hooks/usePropsDebugger.js.map
|
||||
packages/app-desktop/gui/lib/ToggleButton/ToggleButton.d.ts
|
||||
packages/app-desktop/gui/lib/ToggleButton/ToggleButton.js
|
||||
packages/app-desktop/gui/lib/ToggleButton/ToggleButton.js.map
|
||||
packages/app-desktop/gui/menuCommandNames.d.ts
|
||||
packages/app-desktop/gui/menuCommandNames.js
|
||||
packages/app-desktop/gui/menuCommandNames.js.map
|
||||
@@ -1333,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
|
||||
@@ -1342,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
|
||||
@@ -1375,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
|
||||
@@ -1384,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
|
||||
|
||||
12
.eslintrc.js
12
.eslintrc.js
@@ -15,7 +15,8 @@ module.exports = {
|
||||
'Atomics': 'readonly',
|
||||
'SharedArrayBuffer': 'readonly',
|
||||
|
||||
// Jasmine variables
|
||||
// Jest variables
|
||||
'test': 'readonly',
|
||||
'expect': 'readonly',
|
||||
'describe': 'readonly',
|
||||
'it': 'readonly',
|
||||
@@ -23,10 +24,6 @@ module.exports = {
|
||||
'afterAll': 'readonly',
|
||||
'beforeEach': 'readonly',
|
||||
'afterEach': 'readonly',
|
||||
'jasmine': 'readonly',
|
||||
|
||||
// Jest variables
|
||||
'test': 'readonly',
|
||||
|
||||
// React Native variables
|
||||
'__DEV__': 'readonly',
|
||||
@@ -129,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.
|
||||
@@ -155,6 +156,7 @@ module.exports = {
|
||||
'requireLast': false,
|
||||
},
|
||||
}],
|
||||
'@typescript-eslint/no-floating-promises': ['error'],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
129
.gitignore
vendored
129
.gitignore
vendored
@@ -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
|
||||
@@ -233,6 +143,15 @@ packages/app-cli/tests/support/plugins/events/api/types.js.map
|
||||
packages/app-cli/tests/support/plugins/events/src/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/events/src/index.js
|
||||
packages/app-cli/tests/support/plugins/events/src/index.js.map
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/index.js
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/index.js.map
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/types.d.ts
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/types.js
|
||||
packages/app-cli/tests/support/plugins/jpl_test/api/types.js.map
|
||||
packages/app-cli/tests/support/plugins/jpl_test/src/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/jpl_test/src/index.js
|
||||
packages/app-cli/tests/support/plugins/jpl_test/src/index.js.map
|
||||
packages/app-cli/tests/support/plugins/json_export/api/index.d.ts
|
||||
packages/app-cli/tests/support/plugins/json_export/api/index.js
|
||||
packages/app-cli/tests/support/plugins/json_export/api/index.js.map
|
||||
@@ -359,6 +278,9 @@ packages/app-desktop/gui/ConfigScreen/ConfigScreen.js.map
|
||||
packages/app-desktop/gui/ConfigScreen/SideBar.d.ts
|
||||
packages/app-desktop/gui/ConfigScreen/SideBar.js
|
||||
packages/app-desktop/gui/ConfigScreen/SideBar.js.map
|
||||
packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.d.ts
|
||||
packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js
|
||||
packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js.map
|
||||
packages/app-desktop/gui/DropboxLoginScreen.d.ts
|
||||
packages/app-desktop/gui/DropboxLoginScreen.js
|
||||
packages/app-desktop/gui/DropboxLoginScreen.js.map
|
||||
@@ -722,6 +644,9 @@ packages/app-desktop/gui/ToolbarButton/ToolbarButton.js.map
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.d.ts
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.js
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.js.map
|
||||
packages/app-desktop/gui/dialogs.d.ts
|
||||
packages/app-desktop/gui/dialogs.js
|
||||
packages/app-desktop/gui/dialogs.js.map
|
||||
packages/app-desktop/gui/hooks/useEffectDebugger.d.ts
|
||||
packages/app-desktop/gui/hooks/useEffectDebugger.js
|
||||
packages/app-desktop/gui/hooks/useEffectDebugger.js.map
|
||||
@@ -734,6 +659,9 @@ packages/app-desktop/gui/hooks/usePrevious.js.map
|
||||
packages/app-desktop/gui/hooks/usePropsDebugger.d.ts
|
||||
packages/app-desktop/gui/hooks/usePropsDebugger.js
|
||||
packages/app-desktop/gui/hooks/usePropsDebugger.js.map
|
||||
packages/app-desktop/gui/lib/ToggleButton/ToggleButton.d.ts
|
||||
packages/app-desktop/gui/lib/ToggleButton/ToggleButton.js
|
||||
packages/app-desktop/gui/lib/ToggleButton/ToggleButton.js.map
|
||||
packages/app-desktop/gui/menuCommandNames.d.ts
|
||||
packages/app-desktop/gui/menuCommandNames.js
|
||||
packages/app-desktop/gui/menuCommandNames.js.map
|
||||
@@ -1325,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
|
||||
@@ -1334,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
|
||||
@@ -1367,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
|
||||
@@ -1376,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
|
||||
2
BUILD.md
2
BUILD.md
@@ -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
|
||||
|
||||
|
||||
17
README.md
17
README.md
@@ -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
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"_vieux/": true,
|
||||
".gitignore": true,
|
||||
".eslintignore": true,
|
||||
"**/*.jpl": true,
|
||||
"./packages/app-cli/**/*.*~": true,
|
||||
"./packages/app-cli/**/*.mo": true,
|
||||
"./packages/app-cli/**/build/": true,
|
||||
@@ -55,7 +56,6 @@
|
||||
"./packages/app-desktop/**/*.min.js": true,
|
||||
"./packages/app-desktop/**/dist/": true,
|
||||
"./packages/app-desktop/**/gui/note-viewer/pluginAssets/": true,
|
||||
"./packages/app-desktop/**/lib/": true,
|
||||
"./packages/app-desktop/**/node_modules/": true,
|
||||
"./packages/app-desktop/**/packageInfo.js": true,
|
||||
"./packages/app-desktop/**/pluginAssets/": true,
|
||||
@@ -242,7 +242,6 @@
|
||||
"packages/app-desktop/**/*.min.js": true,
|
||||
"packages/app-desktop/**/dist/": true,
|
||||
"packages/app-desktop/**/gui/note-viewer/pluginAssets/": true,
|
||||
"packages/app-desktop/**/lib/": true,
|
||||
"packages/app-desktop/**/node_modules/": true,
|
||||
"packages/app-desktop/**/packageInfo.js": true,
|
||||
"packages/app-desktop/**/pluginAssets/": true,
|
||||
|
||||
22
package-lock.json
generated
22
package-lock.json
generated
@@ -1227,12 +1227,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/jasmine": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.0.tgz",
|
||||
"integrity": "sha512-CPT4r0a63e5wpNj5ejMnconM7a+0Hdx6/APsyw8AQOHk0/Mxp3xYrym1ZabWJiYuQkgKB3MonYoN04mxtvAvRA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
||||
@@ -6439,22 +6433,6 @@
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
|
||||
"dev": true
|
||||
},
|
||||
"jasmine": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.3.tgz",
|
||||
"integrity": "sha512-Th91zHsbsALWjDUIiU5d/W5zaYQsZFMPTdeNmi8GivZPmAaUAK8MblSG3yQI4VMGC/abF2us7ex60NH1AAIMTA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.6",
|
||||
"jasmine-core": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"jasmine-core": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz",
|
||||
"integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
|
||||
15
package.json
15
package.json
@@ -7,6 +7,12 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"addPackageCli": "lerna add --scope joplin",
|
||||
"addPackageCliD": "lerna add --scope joplin -D",
|
||||
"addPackageDesktop": "lerna add --scope @joplin/app-desktop",
|
||||
"addPackageDesktopD": "lerna add --scope @joplin/app-desktop -D",
|
||||
"addPackageMobile": "lerna add --scope @joplin/app-mobile",
|
||||
"addPackageMobileD": "lerna add --scope @joplin/app-mobile -D",
|
||||
"buildApiDoc": "npm start --prefix=packages/app-cli -- apidoc ../../readme/api/references/rest_api.md",
|
||||
"buildDoc": "./packages/tools/build-all.sh",
|
||||
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out docs/api/references/plugin_api packages/lib/services/plugins/api/",
|
||||
@@ -24,12 +30,13 @@
|
||||
"releaseCli": "node packages/tools/release-cli.js",
|
||||
"releaseClipper": "node packages/tools/release-clipper.js",
|
||||
"releaseDesktop": "node packages/tools/release-electron.js",
|
||||
"releasePluginGenerator": "node packages/tools/release-plugin-generator.js",
|
||||
"setupNewRelease": "node ./packages/tools/setupNewRelease",
|
||||
"updatePluginTypes": "./packages/generator-joplin/updateTypes.sh",
|
||||
"tsc": "lerna run tsc --stream --parallel",
|
||||
"test": "lerna run test --stream",
|
||||
"test-ci": "lerna run test-ci --stream",
|
||||
"test": "lerna run test --stream",
|
||||
"tsc": "lerna run tsc --stream --parallel",
|
||||
"updateIgnored": "gulp updateIgnoredTypeScriptBuild",
|
||||
"updatePluginTypes": "./packages/generator-joplin/updateTypes.sh",
|
||||
"watch": "lerna run watch --stream --parallel"
|
||||
},
|
||||
"husky": {
|
||||
@@ -38,7 +45,6 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jasmine": "^3.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.6.0",
|
||||
"@typescript-eslint/parser": "^4.6.0",
|
||||
"eslint": "^7.6.0",
|
||||
@@ -49,7 +55,6 @@
|
||||
"glob": "^7.1.6",
|
||||
"gulp": "^4.0.2",
|
||||
"husky": "^3.0.2",
|
||||
"jasmine": "^3.5.0",
|
||||
"lerna": "^3.22.1",
|
||||
"lint-staged": "^9.2.1",
|
||||
"typedoc": "^0.17.8",
|
||||
|
||||
@@ -426,7 +426,7 @@ class Application extends BaseApplication {
|
||||
|
||||
const AppGui = require('./app-gui.js');
|
||||
this.gui_ = new AppGui(this, this.store(), keymap);
|
||||
this.gui_.setLogger(this.logger_);
|
||||
this.gui_.setLogger(this.logger());
|
||||
await this.gui_.start();
|
||||
|
||||
// Since the settings need to be loaded before the store is created, it will never
|
||||
|
||||
@@ -30,12 +30,12 @@ module.exports = {
|
||||
],
|
||||
|
||||
testPathIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
'/tests\\/support/',
|
||||
'/build/',
|
||||
'test-utils.js',
|
||||
'file_api_driver.js',
|
||||
'/tests\\/tmp/',
|
||||
'<rootDir>/node_modules/',
|
||||
'<rootDir>/tests/support/',
|
||||
'<rootDir>/build/',
|
||||
'<rootDir>/tests/test-utils.js',
|
||||
'<rootDir>/tests/file_api_driver.js',
|
||||
'<rootDir>/tests/tmp/',
|
||||
],
|
||||
|
||||
// To avoid this warning:
|
||||
@@ -52,5 +52,5 @@ module.exports = {
|
||||
],
|
||||
|
||||
testEnvironment: 'node',
|
||||
setupFilesAfterEnv: ['./jest.setup.js'],
|
||||
setupFilesAfterEnv: [`${__dirname}/jest.setup.js`],
|
||||
};
|
||||
|
||||
48
packages/app-cli/package-lock.json
generated
48
packages/app-cli/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "1.4.3",
|
||||
"version": "1.4.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -898,11 +898,15 @@
|
||||
"@types/istanbul-lib-report": "*"
|
||||
}
|
||||
},
|
||||
"@types/jasmine": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.0.tgz",
|
||||
"integrity": "sha512-CPT4r0a63e5wpNj5ejMnconM7a+0Hdx6/APsyw8AQOHk0/Mxp3xYrym1ZabWJiYuQkgKB3MonYoN04mxtvAvRA==",
|
||||
"dev": true
|
||||
"@types/jest": {
|
||||
"version": "26.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.15.tgz",
|
||||
"integrity": "sha512-s2VMReFXRg9XXxV+CW9e5Nz8fH2K1aEhwgjUqPPbQd7g95T0laAcvLv032EhFHIa5GHsZ8W7iJEQVaJq6k3Gog==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jest-diff": "^26.0.0",
|
||||
"pretty-format": "^26.0.0"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.14.6",
|
||||
@@ -4511,38 +4515,6 @@
|
||||
"istanbul-lib-report": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"jasmine": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.5.0.tgz",
|
||||
"integrity": "sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.4",
|
||||
"jasmine-core": "~3.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"glob": {
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz",
|
||||
"integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jasmine-core": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz",
|
||||
"integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==",
|
||||
"dev": true
|
||||
},
|
||||
"jest": {
|
||||
"version": "26.6.3",
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.4.3",
|
||||
"version": "1.4.9",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
@@ -66,10 +66,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "^1.0.9",
|
||||
"@types/jasmine": "^3.6.0",
|
||||
"@types/jest": "^26.0.15",
|
||||
"@types/node": "^14.14.6",
|
||||
"gulp": "^4.0.2",
|
||||
"jasmine": "^3.5.0",
|
||||
"jest": "^26.6.3",
|
||||
"temp": "^0.9.1",
|
||||
"typescript": "^4.0.5"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
99
packages/app-cli/tests/EnexToMd.ts
Normal file
99
packages/app-cli/tests/EnexToMd.ts
Normal 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.',
|
||||
'',
|
||||
'',
|
||||
].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
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
// }
|
||||
// }));
|
||||
|
||||
});
|
||||
|
||||
14
packages/app-cli/tests/enex_to_md/invalid_date.enex
Normal file
14
packages/app-cli/tests/enex_to_md/invalid_date.enex
Normal 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>
|
||||
47
packages/app-cli/tests/enex_to_md/sample-enex.xml
Executable file
47
packages/app-cli/tests/enex_to_md/sample-enex.xml
Executable 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>
|
||||
|
||||
@@ -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);
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -262,14 +262,14 @@ describe('models_Note', function() {
|
||||
for (const testCase of testCases) {
|
||||
const [useAbsolutePaths, input, expected] = testCase;
|
||||
const internalToExternal = await Note.replaceResourceInternalToExternalLinks(input, { useAbsolutePaths });
|
||||
expect(internalToExternal).toBe(expected, 'replaceResourceInternalToExternalLinks failed');
|
||||
expect(internalToExternal).toBe(expected);
|
||||
|
||||
const externalToInternal = await Note.replaceResourceExternalToInternalLinks(internalToExternal, { useAbsolutePaths });
|
||||
expect(externalToInternal).toBe(input, 'replaceResourceExternalToInternalLinks failed');
|
||||
expect(externalToInternal).toBe(input);
|
||||
}
|
||||
|
||||
const result = await Note.replaceResourceExternalToInternalLinks(`[](joplin://${note1.id})`);
|
||||
expect(result).toBe(`[](:/${note1.id})`, 'replaceResourceExternalToInternalLinks failed (note link)');
|
||||
expect(result).toBe(`[](:/${note1.id})`);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ async function recreateExportDir() {
|
||||
function fieldsEqual(model1: any, model2: any, fieldNames: string[]) {
|
||||
for (let i = 0; i < fieldNames.length; i++) {
|
||||
const f = fieldNames[i];
|
||||
expect(model1[f]).toBe(model2[f], `For key ${f}`);
|
||||
expect(model1[f]).toBe(model2[f]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@ 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 { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, createTempDir } = require('./test-utils.js');
|
||||
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');
|
||||
|
||||
@@ -43,7 +45,7 @@ describe('services_PluginService', function() {
|
||||
|
||||
it('should load and run a simple plugin', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/simple`]);
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/simple`], {});
|
||||
|
||||
expect(() => service.pluginById('org.joplinapp.plugins.Simple')).not.toThrowError();
|
||||
|
||||
@@ -59,13 +61,13 @@ describe('services_PluginService', function() {
|
||||
|
||||
it('should load and run a simple plugin and handle trailing slash', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/simple/`]);
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/simple/`], {});
|
||||
expect(() => service.pluginById('org.joplinapp.plugins.Simple')).not.toThrowError();
|
||||
}));
|
||||
|
||||
it('should load and run a plugin that uses external packages', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/withExternalModules`]);
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/withExternalModules`], {});
|
||||
expect(() => service.pluginById('org.joplinapp.plugins.ExternalModuleDemo')).not.toThrowError();
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
@@ -78,7 +80,7 @@ describe('services_PluginService', function() {
|
||||
|
||||
it('should load multiple plugins from a directory', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins(`${testPluginDir}/multi_plugins`);
|
||||
await service.loadAndRunPlugins(`${testPluginDir}/multi_plugins`, {});
|
||||
|
||||
const plugin1 = service.pluginById('org.joplinapp.plugins.MultiPluginDemo1');
|
||||
const plugin2 = service.pluginById('org.joplinapp.plugins.MultiPluginDemo2');
|
||||
@@ -125,14 +127,14 @@ describe('services_PluginService', function() {
|
||||
|
||||
it('should load plugins from JS bundle files', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins(`${testPluginDir}/jsbundles`);
|
||||
await service.loadAndRunPlugins(`${testPluginDir}/jsbundles`, {});
|
||||
expect(!!service.pluginById('org.joplinapp.plugins.JsBundleDemo')).toBe(true);
|
||||
expect((await Folder.all()).length).toBe(1);
|
||||
}));
|
||||
|
||||
it('should load plugins from JPL archive', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/jpl_test/org.joplinapp.FirstJplPlugin.jpl`]);
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/jpl_test/org.joplinapp.FirstJplPlugin.jpl`], {});
|
||||
expect(!!service.pluginById('org.joplinapp.FirstJplPlugin')).toBe(true);
|
||||
expect((await Folder.all()).length).toBe(1);
|
||||
}));
|
||||
@@ -248,10 +250,35 @@ describe('services_PluginService', function() {
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const [appVersion, expected] = testCase;
|
||||
const plugin = await newPluginService(appVersion as string).loadPluginFromJsBundle('', pluginScript);
|
||||
expect(plugin.enabled).toBe(expected as boolean);
|
||||
const [appVersion, hasNoError] = testCase;
|
||||
const service = newPluginService(appVersion as string);
|
||||
const plugin = await service.loadPluginFromJsBundle('', pluginScript);
|
||||
|
||||
if (hasNoError) {
|
||||
await expectNotThrow(() => service.runPlugin(plugin));
|
||||
} else {
|
||||
await expectThrow(() => service.runPlugin(plugin));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
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);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
const time = require('@joplin/lib/time').default;
|
||||
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, mockDate, restoreDate } = require('./test-utils.js');
|
||||
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, restoreDate } = require('./test-utils.js');
|
||||
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine');
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const ItemChange = require('@joplin/lib/models/ItemChange');
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -23,12 +23,6 @@ let engine = null;
|
||||
|
||||
const ids = (array) => array.map(a => a.id);
|
||||
|
||||
// For pretty printing.
|
||||
// See https://stackoverflow.com/questions/23676459/karma-jasmine-pretty-printing-object-comparison/26324116
|
||||
// jasmine.pp = function(obj) {
|
||||
// return JSON.stringify(obj, undefined, 2);
|
||||
// };
|
||||
|
||||
describe('services_SearchFilter', function() {
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
|
||||
@@ -538,7 +538,7 @@ describe('services_rest_Api', function() {
|
||||
const r3 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery, page: 3 });
|
||||
|
||||
expect(r3.items.length).toBe(0);
|
||||
expect(r3.has_more).toBe(undefined);
|
||||
expect(r3.has_more).toBe(false);
|
||||
}
|
||||
|
||||
{
|
||||
@@ -560,7 +560,7 @@ describe('services_rest_Api', function() {
|
||||
|
||||
expect(r2.items.length).toBe(1);
|
||||
expect(r2.items[0].title).toBe('folder4');
|
||||
expect(r2.has_more).toBe(undefined);
|
||||
expect(r2.has_more).toBe(false);
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Command } from './types';
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
@@ -40,8 +40,8 @@ export default class JoplinCommands {
|
||||
* await joplin.commands.execute('newFolder', "SOME_FOLDER_ID");
|
||||
* ```
|
||||
*/
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Registers a new command.
|
||||
*
|
||||
* ```typescript
|
||||
@@ -57,5 +57,5 @@ export default class JoplinCommands {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
register(command: Command): Promise<void>;
|
||||
register(command: Command): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
* so for now disable filters.
|
||||
*/
|
||||
export default class JoplinFilters {
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types';
|
||||
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
|
||||
*/
|
||||
export default class JoplinInterop {
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +26,8 @@ export default class JoplinPlugins {
|
||||
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
|
||||
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
|
||||
*
|
||||
* @param type Defines how the script will be used. See the type definition for more information about each supported type.
|
||||
* @param id A unique ID for the content script.
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, DialogResult } from './types';
|
||||
/**
|
||||
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
|
||||
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return an object indicating what button was clicked
|
||||
* on. If your HTML content included one or more form, a `formData` object will also be included with the key/value for each form.
|
||||
* There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
|
||||
* Allows creating and managing dialogs. A dialog is modal window that
|
||||
* contains a webview and a row of buttons. You can update the update the
|
||||
* webview using the `setHtml` method. Dialogs are hidden by default and
|
||||
* you need to call `open()` to open them. Once the user clicks on a
|
||||
* button, the `open` call will return an object indicating what button was
|
||||
* clicked on.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
* ## Retrieving form values
|
||||
*
|
||||
* If your HTML content included one or more forms, a `formData` object
|
||||
* will also be included with the key/value for each form.
|
||||
*
|
||||
* ## Special button IDs
|
||||
*
|
||||
* The following buttons IDs have a special meaning:
|
||||
*
|
||||
* - `ok`, `yes`, `submit`, `confirm`: They are considered "submit" buttons
|
||||
* - `cancel`, `no`, `reject`: They are considered "dismiss" buttons
|
||||
*
|
||||
* This information is used by the application to determine what action
|
||||
* should be done when the user presses "Enter" or "Escape" within the
|
||||
* dialog. If they press "Enter", the first "submit" button will be
|
||||
* automatically clicked. If they press "Escape" the first "dismiss" button
|
||||
* will be automatically clicked.
|
||||
*
|
||||
* [View the demo
|
||||
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface ExportOptions {
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
@@ -366,5 +366,41 @@ export enum ContentScriptType {
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.
|
||||
*
|
||||
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.
|
||||
*
|
||||
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
|
||||
*
|
||||
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.
|
||||
*
|
||||
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin.
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
|
||||
@@ -400,6 +400,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -787,11 +793,6 @@
|
||||
"wrap-ansi": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"codemirror": {
|
||||
"version": "5.58.2",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.58.2.tgz",
|
||||
"integrity": "sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w=="
|
||||
},
|
||||
"collection-visit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
||||
@@ -1617,6 +1618,18 @@
|
||||
"readable-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
@@ -2155,6 +2168,24 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@@ -2564,6 +2595,12 @@
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"on-build-webpack": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-build-webpack/-/on-build-webpack-0.1.0.tgz",
|
||||
"integrity": "sha1-oofA4Xdm5hQZJuXyy7DYu1O3aBQ=",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -3788,6 +3825,12 @@
|
||||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
|
||||
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Command } from './types';
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
@@ -40,8 +40,8 @@ export default class JoplinCommands {
|
||||
* await joplin.commands.execute('newFolder', "SOME_FOLDER_ID");
|
||||
* ```
|
||||
*/
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Registers a new command.
|
||||
*
|
||||
* ```typescript
|
||||
@@ -57,5 +57,5 @@ export default class JoplinCommands {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
register(command: Command): Promise<void>;
|
||||
register(command: Command): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
* so for now disable filters.
|
||||
*/
|
||||
export default class JoplinFilters {
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types';
|
||||
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
|
||||
*/
|
||||
export default class JoplinInterop {
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +26,8 @@ export default class JoplinPlugins {
|
||||
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
|
||||
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
|
||||
*
|
||||
* @param type Defines how the script will be used. See the type definition for more information about each supported type.
|
||||
* @param id A unique ID for the content script.
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, DialogResult } from './types';
|
||||
/**
|
||||
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
|
||||
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return an object indicating what button was clicked
|
||||
* on. If your HTML content included one or more form, a `formData` object will also be included with the key/value for each form.
|
||||
* There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
|
||||
* Allows creating and managing dialogs. A dialog is modal window that
|
||||
* contains a webview and a row of buttons. You can update the update the
|
||||
* webview using the `setHtml` method. Dialogs are hidden by default and
|
||||
* you need to call `open()` to open them. Once the user clicks on a
|
||||
* button, the `open` call will return an object indicating what button was
|
||||
* clicked on.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
* ## Retrieving form values
|
||||
*
|
||||
* If your HTML content included one or more forms, a `formData` object
|
||||
* will also be included with the key/value for each form.
|
||||
*
|
||||
* ## Special button IDs
|
||||
*
|
||||
* The following buttons IDs have a special meaning:
|
||||
*
|
||||
* - `ok`, `yes`, `submit`, `confirm`: They are considered "submit" buttons
|
||||
* - `cancel`, `no`, `reject`: They are considered "dismiss" buttons
|
||||
*
|
||||
* This information is used by the application to determine what action
|
||||
* should be done when the user presses "Enter" or "Escape" within the
|
||||
* dialog. If they press "Enter", the first "submit" button will be
|
||||
* automatically clicked. If they press "Escape" the first "dismiss" button
|
||||
* will be automatically clicked.
|
||||
*
|
||||
* [View the demo
|
||||
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface ExportOptions {
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
@@ -366,5 +366,41 @@ export enum ContentScriptType {
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.
|
||||
*
|
||||
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.
|
||||
*
|
||||
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
|
||||
*
|
||||
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.
|
||||
*
|
||||
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin.
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
|
||||
@@ -400,6 +400,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -1612,6 +1618,18 @@
|
||||
"readable-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
@@ -2150,6 +2168,24 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@@ -2559,6 +2595,12 @@
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"on-build-webpack": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-build-webpack/-/on-build-webpack-0.1.0.tgz",
|
||||
"integrity": "sha1-oofA4Xdm5hQZJuXyy7DYu1O3aBQ=",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -3783,6 +3825,12 @@
|
||||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
|
||||
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Command } from './types';
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
@@ -40,8 +40,8 @@ export default class JoplinCommands {
|
||||
* await joplin.commands.execute('newFolder', "SOME_FOLDER_ID");
|
||||
* ```
|
||||
*/
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Registers a new command.
|
||||
*
|
||||
* ```typescript
|
||||
@@ -57,5 +57,5 @@ export default class JoplinCommands {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
register(command: Command): Promise<void>;
|
||||
register(command: Command): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
* so for now disable filters.
|
||||
*/
|
||||
export default class JoplinFilters {
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types';
|
||||
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
|
||||
*/
|
||||
export default class JoplinInterop {
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +26,8 @@ export default class JoplinPlugins {
|
||||
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
|
||||
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
|
||||
*
|
||||
* @param type Defines how the script will be used. See the type definition for more information about each supported type.
|
||||
* @param id A unique ID for the content script.
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, DialogResult } from './types';
|
||||
/**
|
||||
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
|
||||
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return an object indicating what button was clicked
|
||||
* on. If your HTML content included one or more form, a `formData` object will also be included with the key/value for each form.
|
||||
* There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
|
||||
* Allows creating and managing dialogs. A dialog is modal window that
|
||||
* contains a webview and a row of buttons. You can update the update the
|
||||
* webview using the `setHtml` method. Dialogs are hidden by default and
|
||||
* you need to call `open()` to open them. Once the user clicks on a
|
||||
* button, the `open` call will return an object indicating what button was
|
||||
* clicked on.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
* ## Retrieving form values
|
||||
*
|
||||
* If your HTML content included one or more forms, a `formData` object
|
||||
* will also be included with the key/value for each form.
|
||||
*
|
||||
* ## Special button IDs
|
||||
*
|
||||
* The following buttons IDs have a special meaning:
|
||||
*
|
||||
* - `ok`, `yes`, `submit`, `confirm`: They are considered "submit" buttons
|
||||
* - `cancel`, `no`, `reject`: They are considered "dismiss" buttons
|
||||
*
|
||||
* This information is used by the application to determine what action
|
||||
* should be done when the user presses "Enter" or "Escape" within the
|
||||
* dialog. If they press "Enter", the first "submit" button will be
|
||||
* automatically clicked. If they press "Escape" the first "dismiss" button
|
||||
* will be automatically clicked.
|
||||
*
|
||||
* [View the demo
|
||||
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface ExportOptions {
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
@@ -366,5 +366,41 @@ export enum ContentScriptType {
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.
|
||||
*
|
||||
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.
|
||||
*
|
||||
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
|
||||
*
|
||||
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.
|
||||
*
|
||||
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin.
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
|
||||
@@ -400,6 +400,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -1612,6 +1618,18 @@
|
||||
"readable-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
@@ -2150,6 +2168,24 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@@ -2559,6 +2595,12 @@
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"on-build-webpack": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-build-webpack/-/on-build-webpack-0.1.0.tgz",
|
||||
"integrity": "sha1-oofA4Xdm5hQZJuXyy7DYu1O3aBQ=",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -3783,6 +3825,12 @@
|
||||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
|
||||
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Command } from './types';
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
@@ -40,8 +40,8 @@ export default class JoplinCommands {
|
||||
* await joplin.commands.execute('newFolder', "SOME_FOLDER_ID");
|
||||
* ```
|
||||
*/
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Registers a new command.
|
||||
*
|
||||
* ```typescript
|
||||
@@ -57,5 +57,5 @@ export default class JoplinCommands {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
register(command: Command): Promise<void>;
|
||||
register(command: Command): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
* so for now disable filters.
|
||||
*/
|
||||
export default class JoplinFilters {
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types';
|
||||
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
|
||||
*/
|
||||
export default class JoplinInterop {
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +26,8 @@ export default class JoplinPlugins {
|
||||
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
|
||||
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
|
||||
*
|
||||
* @param type Defines how the script will be used. See the type definition for more information about each supported type.
|
||||
* @param id A unique ID for the content script.
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, DialogResult } from './types';
|
||||
/**
|
||||
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
|
||||
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return an object indicating what button was clicked
|
||||
* on. If your HTML content included one or more form, a `formData` object will also be included with the key/value for each form.
|
||||
* There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
|
||||
* Allows creating and managing dialogs. A dialog is modal window that
|
||||
* contains a webview and a row of buttons. You can update the update the
|
||||
* webview using the `setHtml` method. Dialogs are hidden by default and
|
||||
* you need to call `open()` to open them. Once the user clicks on a
|
||||
* button, the `open` call will return an object indicating what button was
|
||||
* clicked on.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
* ## Retrieving form values
|
||||
*
|
||||
* If your HTML content included one or more forms, a `formData` object
|
||||
* will also be included with the key/value for each form.
|
||||
*
|
||||
* ## Special button IDs
|
||||
*
|
||||
* The following buttons IDs have a special meaning:
|
||||
*
|
||||
* - `ok`, `yes`, `submit`, `confirm`: They are considered "submit" buttons
|
||||
* - `cancel`, `no`, `reject`: They are considered "dismiss" buttons
|
||||
*
|
||||
* This information is used by the application to determine what action
|
||||
* should be done when the user presses "Enter" or "Escape" within the
|
||||
* dialog. If they press "Enter", the first "submit" button will be
|
||||
* automatically clicked. If they press "Escape" the first "dismiss" button
|
||||
* will be automatically clicked.
|
||||
*
|
||||
* [View the demo
|
||||
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface ExportOptions {
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
@@ -366,5 +366,41 @@ export enum ContentScriptType {
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.
|
||||
*
|
||||
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.
|
||||
*
|
||||
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
|
||||
*
|
||||
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.
|
||||
*
|
||||
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin.
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
|
||||
@@ -400,6 +400,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -1621,6 +1627,18 @@
|
||||
"readable-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
@@ -2159,6 +2177,24 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@@ -2575,6 +2611,12 @@
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"on-build-webpack": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-build-webpack/-/on-build-webpack-0.1.0.tgz",
|
||||
"integrity": "sha1-oofA4Xdm5hQZJuXyy7DYu1O3aBQ=",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -3799,6 +3841,12 @@
|
||||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
|
||||
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Command } from './types';
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
@@ -40,8 +40,8 @@ export default class JoplinCommands {
|
||||
* await joplin.commands.execute('newFolder', "SOME_FOLDER_ID");
|
||||
* ```
|
||||
*/
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Registers a new command.
|
||||
*
|
||||
* ```typescript
|
||||
@@ -57,5 +57,5 @@ export default class JoplinCommands {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
register(command: Command): Promise<void>;
|
||||
register(command: Command): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
* so for now disable filters.
|
||||
*/
|
||||
export default class JoplinFilters {
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types';
|
||||
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
|
||||
*/
|
||||
export default class JoplinInterop {
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +26,8 @@ export default class JoplinPlugins {
|
||||
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
|
||||
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
|
||||
*
|
||||
* @param type Defines how the script will be used. See the type definition for more information about each supported type.
|
||||
* @param id A unique ID for the content script.
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, DialogResult } from './types';
|
||||
/**
|
||||
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
|
||||
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return an object indicating what button was clicked
|
||||
* on. If your HTML content included one or more form, a `formData` object will also be included with the key/value for each form.
|
||||
* There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
|
||||
* Allows creating and managing dialogs. A dialog is modal window that
|
||||
* contains a webview and a row of buttons. You can update the update the
|
||||
* webview using the `setHtml` method. Dialogs are hidden by default and
|
||||
* you need to call `open()` to open them. Once the user clicks on a
|
||||
* button, the `open` call will return an object indicating what button was
|
||||
* clicked on.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
* ## Retrieving form values
|
||||
*
|
||||
* If your HTML content included one or more forms, a `formData` object
|
||||
* will also be included with the key/value for each form.
|
||||
*
|
||||
* ## Special button IDs
|
||||
*
|
||||
* The following buttons IDs have a special meaning:
|
||||
*
|
||||
* - `ok`, `yes`, `submit`, `confirm`: They are considered "submit" buttons
|
||||
* - `cancel`, `no`, `reject`: They are considered "dismiss" buttons
|
||||
*
|
||||
* This information is used by the application to determine what action
|
||||
* should be done when the user presses "Enter" or "Escape" within the
|
||||
* dialog. If they press "Enter", the first "submit" button will be
|
||||
* automatically clicked. If they press "Escape" the first "dismiss" button
|
||||
* will be automatically clicked.
|
||||
*
|
||||
* [View the demo
|
||||
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface ExportOptions {
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
@@ -366,5 +366,41 @@ export enum ContentScriptType {
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.
|
||||
*
|
||||
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.
|
||||
*
|
||||
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
|
||||
*
|
||||
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.
|
||||
*
|
||||
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin.
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
|
||||
@@ -400,6 +400,12 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
@@ -1612,6 +1618,18 @@
|
||||
"readable-stream": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
|
||||
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"at-least-node": "^1.0.0",
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
@@ -2150,6 +2168,24 @@
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"universalify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
|
||||
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
|
||||
@@ -2559,6 +2595,12 @@
|
||||
"isobject": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"on-build-webpack": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-build-webpack/-/on-build-webpack-0.1.0.tgz",
|
||||
"integrity": "sha1-oofA4Xdm5hQZJuXyy7DYu1O3aBQ=",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -3783,6 +3825,12 @@
|
||||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
|
||||
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
17
packages/app-cli/tests/support/plugins/installPlugins.sh
Executable file
17
packages/app-cli/tests/support/plugins/installPlugins.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
|
||||
# cd "$SCRIPT_DIR/jpl_test/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/codemirror_content_script/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/content_script/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/dialog/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/editor_context_menu/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/events/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/json_export/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/menu/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/multi_selection/" && npm i && \
|
||||
# cd "$SCRIPT_DIR/register_command/" && npm i && \
|
||||
cd "$SCRIPT_DIR/selected_text/" && npm i && \
|
||||
cd "$SCRIPT_DIR/settings/" && npm i && \
|
||||
cd "$SCRIPT_DIR/toc/" && npm i && \
|
||||
cd "$SCRIPT_DIR/withExternalModules/" && npm i
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Command } from './types';
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
@@ -40,8 +40,8 @@ export default class JoplinCommands {
|
||||
* await joplin.commands.execute('newFolder', "SOME_FOLDER_ID");
|
||||
* ```
|
||||
*/
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
execute(commandName: string, ...args: any[]): Promise<any | void>;
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Registers a new command.
|
||||
*
|
||||
* ```typescript
|
||||
@@ -57,5 +57,5 @@ export default class JoplinCommands {
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
register(command: Command): Promise<void>;
|
||||
register(command: Command): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
* so for now disable filters.
|
||||
*/
|
||||
export default class JoplinFilters {
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
on(name: string, callback: Function): Promise<void>;
|
||||
off(name: string, callback: Function): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types';
|
||||
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
|
||||
*/
|
||||
export default class JoplinInterop {
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
registerExportModule(module: ExportModule): Promise<void>;
|
||||
registerImportModule(module: ImportModule): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -28,7 +26,8 @@ export default class JoplinPlugins {
|
||||
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules
|
||||
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
|
||||
*
|
||||
* @param type Defines how the script will be used. See the type definition for more information about each supported type.
|
||||
* @param id A unique ID for the content script.
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, DialogResult } from './types';
|
||||
/**
|
||||
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
|
||||
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return an object indicating what button was clicked
|
||||
* on. If your HTML content included one or more form, a `formData` object will also be included with the key/value for each form.
|
||||
* There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
|
||||
* Allows creating and managing dialogs. A dialog is modal window that
|
||||
* contains a webview and a row of buttons. You can update the update the
|
||||
* webview using the `setHtml` method. Dialogs are hidden by default and
|
||||
* you need to call `open()` to open them. Once the user clicks on a
|
||||
* button, the `open` call will return an object indicating what button was
|
||||
* clicked on.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
* ## Retrieving form values
|
||||
*
|
||||
* If your HTML content included one or more forms, a `formData` object
|
||||
* will also be included with the key/value for each form.
|
||||
*
|
||||
* ## Special button IDs
|
||||
*
|
||||
* The following buttons IDs have a special meaning:
|
||||
*
|
||||
* - `ok`, `yes`, `submit`, `confirm`: They are considered "submit" buttons
|
||||
* - `cancel`, `no`, `reject`: They are considered "dismiss" buttons
|
||||
*
|
||||
* This information is used by the application to determine what action
|
||||
* should be done when the user presses "Enter" or "Escape" within the
|
||||
* dialog. If they press "Enter", the first "submit" button will be
|
||||
* automatically clicked. If they press "Escape" the first "dismiss" button
|
||||
* will be automatically clicked.
|
||||
*
|
||||
* [View the demo
|
||||
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
|
||||
@@ -161,7 +161,7 @@ export interface ExportOptions {
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
@@ -366,5 +366,41 @@ export enum ContentScriptType {
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate.
|
||||
*
|
||||
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed.
|
||||
*
|
||||
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
|
||||
*
|
||||
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay.
|
||||
*
|
||||
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin.
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "org.joplinapp.FirstJplPlugin",
|
||||
"name": "joplin_plugin",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -7,12 +7,14 @@ The main two files you will want to look at are:
|
||||
- `/src/index.ts`, which contains the entry point for the plugin source code.
|
||||
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
|
||||
|
||||
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Building the plugin
|
||||
|
||||
The plugin is built using Webpack, which creates the compiled code in `/dist`. A JPL archive will also be created at the root, which can use to distribute the plugin.
|
||||
|
||||
To build the plugin, simply run `npm run dist`.
|
||||
|
||||
The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
|
||||
|
||||
## Updating the plugin framework
|
||||
|
||||
To update the plugin framework, run `yo joplin --update`
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user