You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-29 23:48:19 +02:00
Compare commits
47 Commits
orphaned_r
...
plugin_edi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46c40ce9fa | ||
|
|
7151a48138 | ||
|
|
536788f1bc | ||
|
|
aaaa4e4569 | ||
|
|
872d2942b4 | ||
|
|
918b768634 | ||
|
|
8305eb4403 | ||
|
|
91e7c66f9e | ||
|
|
e392efc091 | ||
|
|
458ae3731d | ||
|
|
a647272cf0 | ||
|
|
72472c13c5 | ||
|
|
67f0739d3c | ||
|
|
17d835d694 | ||
|
|
42799b0662 | ||
|
|
d20694e52c | ||
|
|
62feb7ff60 | ||
|
|
e29e745b96 | ||
|
|
340312fa80 | ||
|
|
006239913e | ||
|
|
f4bc8cc817 | ||
|
|
fb1f43bb17 | ||
|
|
31ffd8d7e9 | ||
|
|
873184f69b | ||
|
|
da6977569f | ||
|
|
8808b38d83 | ||
|
|
ad654e30d5 | ||
|
|
6f11487dba | ||
|
|
dd0d54d4d0 | ||
|
|
0fd0451c17 | ||
|
|
06f2fda946 | ||
|
|
c249333e2a | ||
|
|
9755a69be8 | ||
|
|
18e4f7ffe7 | ||
|
|
7cb60aaace | ||
|
|
fbcfe432c5 | ||
|
|
ed71726e87 | ||
|
|
31a0449e71 | ||
|
|
04450a6464 | ||
|
|
d0ec598ee4 | ||
|
|
ca8b05631a | ||
|
|
3223fd26f4 | ||
|
|
7847aeda75 | ||
|
|
7d02ddfdb5 | ||
|
|
5079cd9ff2 | ||
|
|
48f6412721 | ||
|
|
498e80f2d3 |
@@ -169,9 +169,6 @@ packages/app-cli/tests/fsDriver.js.map
|
||||
packages/app-cli/tests/models_Setting.d.ts
|
||||
packages/app-cli/tests/models_Setting.js
|
||||
packages/app-cli/tests/models_Setting.js.map
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSetting.d.ts
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSetting.js
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSetting.js.map
|
||||
packages/app-cli/tests/services/plugins/sandboxProxy.d.ts
|
||||
packages/app-cli/tests/services/plugins/sandboxProxy.js
|
||||
packages/app-cli/tests/services/plugins/sandboxProxy.js.map
|
||||
@@ -436,6 +433,9 @@ packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js.map
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.d.ts
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js.map
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.d.ts
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js.map
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.d.ts
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js.map
|
||||
@@ -502,6 +502,9 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js.map
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupContextMenu.d.ts
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupContextMenu.js.map
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.d.ts
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js.map
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.d.ts
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js.map
|
||||
@@ -583,6 +586,9 @@ packages/app-desktop/gui/NoteListControls/commands/focusSearch.js.map
|
||||
packages/app-desktop/gui/NoteListItem.d.ts
|
||||
packages/app-desktop/gui/NoteListItem.js
|
||||
packages/app-desktop/gui/NoteListItem.js.map
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.d.ts
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.js
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.js.map
|
||||
packages/app-desktop/gui/NoteTextViewer.d.ts
|
||||
packages/app-desktop/gui/NoteTextViewer.js
|
||||
packages/app-desktop/gui/NoteTextViewer.js.map
|
||||
@@ -592,15 +598,60 @@ packages/app-desktop/gui/NoteToolbar/NoteToolbar.js.map
|
||||
packages/app-desktop/gui/OneDriveLoginScreen.d.ts
|
||||
packages/app-desktop/gui/OneDriveLoginScreen.js
|
||||
packages/app-desktop/gui/OneDriveLoginScreen.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/MoveButtons.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/MoveButtons.js
|
||||
packages/app-desktop/gui/ResizableLayout/MoveButtons.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/ResizableLayout.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/ResizableLayout.js
|
||||
packages/app-desktop/gui/ResizableLayout/ResizableLayout.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useLayoutItemSizes.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useLayoutItemSizes.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useWindowResizeEvent.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useWindowResizeEvent.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.js.map
|
||||
packages/app-desktop/gui/ResourceScreen.d.ts
|
||||
packages/app-desktop/gui/ResourceScreen.js
|
||||
packages/app-desktop/gui/ResourceScreen.js.map
|
||||
@@ -613,9 +664,6 @@ packages/app-desktop/gui/Root_UpgradeSyncTarget.js.map
|
||||
packages/app-desktop/gui/SearchBar/SearchBar.d.ts
|
||||
packages/app-desktop/gui/SearchBar/SearchBar.js
|
||||
packages/app-desktop/gui/SearchBar/SearchBar.js.map
|
||||
packages/app-desktop/gui/SearchBar/hooks/useSearch.d.ts
|
||||
packages/app-desktop/gui/SearchBar/hooks/useSearch.js
|
||||
packages/app-desktop/gui/SearchBar/hooks/useSearch.js.map
|
||||
packages/app-desktop/gui/SearchBar/styles/index.d.ts
|
||||
packages/app-desktop/gui/SearchBar/styles/index.js
|
||||
packages/app-desktop/gui/SearchBar/styles/index.js.map
|
||||
@@ -682,6 +730,9 @@ packages/app-desktop/plugins/GotoAnything.js.map
|
||||
packages/app-desktop/services/bridge.d.ts
|
||||
packages/app-desktop/services/bridge.js
|
||||
packages/app-desktop/services/bridge.js.map
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.d.ts
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.js
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.js.map
|
||||
packages/app-desktop/services/commands/types.d.ts
|
||||
packages/app-desktop/services/commands/types.js
|
||||
packages/app-desktop/services/commands/types.js.map
|
||||
@@ -859,9 +910,9 @@ packages/lib/models/NoteResource.js.map
|
||||
packages/lib/models/Setting.d.ts
|
||||
packages/lib/models/Setting.js
|
||||
packages/lib/models/Setting.js.map
|
||||
packages/lib/models/utils/modelFeed.d.ts
|
||||
packages/lib/models/utils/modelFeed.js
|
||||
packages/lib/models/utils/modelFeed.js.map
|
||||
packages/lib/models/utils/paginatedFeed.d.ts
|
||||
packages/lib/models/utils/paginatedFeed.js
|
||||
packages/lib/models/utils/paginatedFeed.js.map
|
||||
packages/lib/models/utils/paginationToSql.d.ts
|
||||
packages/lib/models/utils/paginationToSql.js
|
||||
packages/lib/models/utils/paginationToSql.js.map
|
||||
@@ -931,6 +982,9 @@ packages/lib/services/commands/stateToWhenClauseContext.js.map
|
||||
packages/lib/services/contextkey/contextkey.d.ts
|
||||
packages/lib/services/contextkey/contextkey.js
|
||||
packages/lib/services/contextkey/contextkey.js.map
|
||||
packages/lib/services/database/types.d.ts
|
||||
packages/lib/services/database/types.js
|
||||
packages/lib/services/database/types.js.map
|
||||
packages/lib/services/debug/populateDatabase.d.ts
|
||||
packages/lib/services/debug/populateDatabase.js
|
||||
packages/lib/services/debug/populateDatabase.js.map
|
||||
@@ -1120,6 +1174,9 @@ packages/lib/services/rest/routes/search.js.map
|
||||
packages/lib/services/rest/routes/tags.d.ts
|
||||
packages/lib/services/rest/routes/tags.js
|
||||
packages/lib/services/rest/routes/tags.js.map
|
||||
packages/lib/services/rest/utils/collectionToPaginatedResults.d.ts
|
||||
packages/lib/services/rest/utils/collectionToPaginatedResults.js
|
||||
packages/lib/services/rest/utils/collectionToPaginatedResults.js.map
|
||||
packages/lib/services/rest/utils/defaultAction.d.ts
|
||||
packages/lib/services/rest/utils/defaultAction.js
|
||||
packages/lib/services/rest/utils/defaultAction.js.map
|
||||
|
||||
25
.eslintrc.js
25
.eslintrc.js
@@ -25,6 +25,9 @@ module.exports = {
|
||||
'afterEach': 'readonly',
|
||||
'jasmine': 'readonly',
|
||||
|
||||
// Jest variables
|
||||
'test': 'readonly',
|
||||
|
||||
// React Native variables
|
||||
'__DEV__': 'readonly',
|
||||
|
||||
@@ -130,6 +133,28 @@ module.exports = {
|
||||
// Warn only because it would make it difficult to convert JS classes to TypeScript, unless we
|
||||
// make everything public which is not great. New code however should specify member accessibility.
|
||||
'@typescript-eslint/explicit-member-accessibility': ['warn'],
|
||||
'@typescript-eslint/type-annotation-spacing': ['error', { 'before': false, 'after': true }],
|
||||
'@typescript-eslint/comma-dangle': ['error', {
|
||||
'arrays': 'always-multiline',
|
||||
'objects': 'always-multiline',
|
||||
'imports': 'always-multiline',
|
||||
'exports': 'always-multiline',
|
||||
'enums': 'always-multiline',
|
||||
'generics': 'always-multiline',
|
||||
'tuples': 'always-multiline',
|
||||
'functions': 'never',
|
||||
}],
|
||||
'@typescript-eslint/semi': ['error', 'always'],
|
||||
'@typescript-eslint/member-delimiter-style': ['error', {
|
||||
'multiline': {
|
||||
'delimiter': 'semi',
|
||||
'requireLast': true,
|
||||
},
|
||||
'singleline': {
|
||||
'delimiter': 'semi',
|
||||
'requireLast': false,
|
||||
},
|
||||
}],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
---
|
||||
name: "\U0001F914 Feature requests and support"
|
||||
about: 'For non-bug issues we recommend using the forum, where you''ll be more likely
|
||||
to get an answer: https://discourse.joplinapp.org/'
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
If this is a feature request or a support query, please note that you'll not get an answer here.
|
||||
|
||||
Instead we recommend using the forum where you'll are a lot more likely to get an answer: https://discourse.joplinapp.org/
|
||||
|
||||
The forum is also the right place to submit a feature request so that it can be discussed by other users.
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: "\U0001F914 Feature requests and support"
|
||||
url: https://discourse.joplinapp.org/
|
||||
about: I have a question or feature request …
|
||||
87
.gitignore
vendored
87
.gitignore
vendored
@@ -161,9 +161,6 @@ packages/app-cli/tests/fsDriver.js.map
|
||||
packages/app-cli/tests/models_Setting.d.ts
|
||||
packages/app-cli/tests/models_Setting.js
|
||||
packages/app-cli/tests/models_Setting.js.map
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSetting.d.ts
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSetting.js
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSetting.js.map
|
||||
packages/app-cli/tests/services/plugins/sandboxProxy.d.ts
|
||||
packages/app-cli/tests/services/plugins/sandboxProxy.js
|
||||
packages/app-cli/tests/services/plugins/sandboxProxy.js.map
|
||||
@@ -428,6 +425,9 @@ packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js.map
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.d.ts
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleEditors.js.map
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.d.ts
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js.map
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.d.ts
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js
|
||||
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js.map
|
||||
@@ -494,6 +494,9 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js.map
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupContextMenu.d.ts
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupContextMenu.js.map
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.d.ts
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js.map
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.d.ts
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js.map
|
||||
@@ -575,6 +578,9 @@ packages/app-desktop/gui/NoteListControls/commands/focusSearch.js.map
|
||||
packages/app-desktop/gui/NoteListItem.d.ts
|
||||
packages/app-desktop/gui/NoteListItem.js
|
||||
packages/app-desktop/gui/NoteListItem.js.map
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.d.ts
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.js
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.js.map
|
||||
packages/app-desktop/gui/NoteTextViewer.d.ts
|
||||
packages/app-desktop/gui/NoteTextViewer.js
|
||||
packages/app-desktop/gui/NoteTextViewer.js.map
|
||||
@@ -584,15 +590,60 @@ packages/app-desktop/gui/NoteToolbar/NoteToolbar.js.map
|
||||
packages/app-desktop/gui/OneDriveLoginScreen.d.ts
|
||||
packages/app-desktop/gui/OneDriveLoginScreen.js
|
||||
packages/app-desktop/gui/OneDriveLoginScreen.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/MoveButtons.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/MoveButtons.js
|
||||
packages/app-desktop/gui/ResizableLayout/MoveButtons.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/ResizableLayout.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/ResizableLayout.js
|
||||
packages/app-desktop/gui/ResizableLayout/ResizableLayout.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useLayoutItemSizes.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useLayoutItemSizes.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useWindowResizeEvent.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
packages/app-desktop/gui/ResizableLayout/hooks/useWindowResizeEvent.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/findItemByKey.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/isTempContainer.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/iterateItems.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/layoutItemProp.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/movements.test.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/persist.test.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/removeItem.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/setLayoutItemProps.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/style.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/types.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useLayoutItemSizes.test.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/useWindowResizeEvent.js.map
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.d.ts
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.js
|
||||
packages/app-desktop/gui/ResizableLayout/utils/validateLayout.js.map
|
||||
packages/app-desktop/gui/ResourceScreen.d.ts
|
||||
packages/app-desktop/gui/ResourceScreen.js
|
||||
packages/app-desktop/gui/ResourceScreen.js.map
|
||||
@@ -605,9 +656,6 @@ packages/app-desktop/gui/Root_UpgradeSyncTarget.js.map
|
||||
packages/app-desktop/gui/SearchBar/SearchBar.d.ts
|
||||
packages/app-desktop/gui/SearchBar/SearchBar.js
|
||||
packages/app-desktop/gui/SearchBar/SearchBar.js.map
|
||||
packages/app-desktop/gui/SearchBar/hooks/useSearch.d.ts
|
||||
packages/app-desktop/gui/SearchBar/hooks/useSearch.js
|
||||
packages/app-desktop/gui/SearchBar/hooks/useSearch.js.map
|
||||
packages/app-desktop/gui/SearchBar/styles/index.d.ts
|
||||
packages/app-desktop/gui/SearchBar/styles/index.js
|
||||
packages/app-desktop/gui/SearchBar/styles/index.js.map
|
||||
@@ -674,6 +722,9 @@ packages/app-desktop/plugins/GotoAnything.js.map
|
||||
packages/app-desktop/services/bridge.d.ts
|
||||
packages/app-desktop/services/bridge.js
|
||||
packages/app-desktop/services/bridge.js.map
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.d.ts
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.js
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.js.map
|
||||
packages/app-desktop/services/commands/types.d.ts
|
||||
packages/app-desktop/services/commands/types.js
|
||||
packages/app-desktop/services/commands/types.js.map
|
||||
@@ -851,9 +902,9 @@ packages/lib/models/NoteResource.js.map
|
||||
packages/lib/models/Setting.d.ts
|
||||
packages/lib/models/Setting.js
|
||||
packages/lib/models/Setting.js.map
|
||||
packages/lib/models/utils/modelFeed.d.ts
|
||||
packages/lib/models/utils/modelFeed.js
|
||||
packages/lib/models/utils/modelFeed.js.map
|
||||
packages/lib/models/utils/paginatedFeed.d.ts
|
||||
packages/lib/models/utils/paginatedFeed.js
|
||||
packages/lib/models/utils/paginatedFeed.js.map
|
||||
packages/lib/models/utils/paginationToSql.d.ts
|
||||
packages/lib/models/utils/paginationToSql.js
|
||||
packages/lib/models/utils/paginationToSql.js.map
|
||||
@@ -923,6 +974,9 @@ packages/lib/services/commands/stateToWhenClauseContext.js.map
|
||||
packages/lib/services/contextkey/contextkey.d.ts
|
||||
packages/lib/services/contextkey/contextkey.js
|
||||
packages/lib/services/contextkey/contextkey.js.map
|
||||
packages/lib/services/database/types.d.ts
|
||||
packages/lib/services/database/types.js
|
||||
packages/lib/services/database/types.js.map
|
||||
packages/lib/services/debug/populateDatabase.d.ts
|
||||
packages/lib/services/debug/populateDatabase.js
|
||||
packages/lib/services/debug/populateDatabase.js.map
|
||||
@@ -1112,6 +1166,9 @@ packages/lib/services/rest/routes/search.js.map
|
||||
packages/lib/services/rest/routes/tags.d.ts
|
||||
packages/lib/services/rest/routes/tags.js
|
||||
packages/lib/services/rest/routes/tags.js.map
|
||||
packages/lib/services/rest/utils/collectionToPaginatedResults.d.ts
|
||||
packages/lib/services/rest/utils/collectionToPaginatedResults.js
|
||||
packages/lib/services/rest/utils/collectionToPaginatedResults.js.map
|
||||
packages/lib/services/rest/utils/defaultAction.d.ts
|
||||
packages/lib/services/rest/utils/defaultAction.js
|
||||
packages/lib/services/rest/utils/defaultAction.js.map
|
||||
|
||||
@@ -66,13 +66,11 @@ script:
|
||||
# Only do it for pull requests because Travis randomly fails to run them
|
||||
# and that would break the desktop release.
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
cd packages/app-cli
|
||||
npm run test-ci
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
fi
|
||||
cd ../..
|
||||
fi
|
||||
|
||||
# Run linter for pull requests only - this is so that
|
||||
|
||||
@@ -64,7 +64,7 @@ The Web Clipper is a browser extension that allows you to save web pages and scr
|
||||
| :---: | :---: | :---: |
|
||||
| <img width="50" src="https://avatars0.githubusercontent.com/u/6979755?s=96&v=4"/></br>[Devon Zuegel](https://github.com/devonzuegel) | <img width="50" src="https://avatars2.githubusercontent.com/u/24908652?s=96&v=4"/></br>[小西 孝宗](https://github.com/konishi-t) | <img width="50" src="https://avatars2.githubusercontent.com/u/215668?s=96&v=4"/></br>[Alexander van der Berg](https://github.com/avanderberg)
|
||||
| <img width="50" src="https://avatars0.githubusercontent.com/u/1168659?s=96&v=4"/></br>[Nicholas Head](https://github.com/nicholashead) | <img width="50" src="https://avatars2.githubusercontent.com/u/1439535?s=96&v=4"/></br>[Frank Bloise](https://github.com/fbloise) | <img width="50" src="https://avatars2.githubusercontent.com/u/15859362?s=96&v=4"/></br>[Thomas Broussard](https://github.com/thomasbroussard)
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[Brandon Johnson](https://github.com/dbrandonjohnson) | |
|
||||
| <img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br>[Brandon Johnson](https://github.com/dbrandonjohnson) | <img width="50" src="https://avatars1.githubusercontent.com/u/3061769?s=96&v=4"/></br>[@cnagy](https://github.com/c-nagy) |
|
||||
|
||||
<!-- TOC -->
|
||||
# Table of contents
|
||||
@@ -318,6 +318,8 @@ The currently supported template variables are:
|
||||
| `{{time}}` | Current time formatted based on the settings format | 13:00 |
|
||||
| `{{datetime}}` | Current date and time formatted based on the settings format | 01/01/19 1:00 PM |
|
||||
| `{{#custom_datetime}}` | Current date and/or time formatted based on a supplied string (using [moment.js](https://momentjs.com/) formatting) | `{{#custom_datetime}}M d{{/custom_datetime}}` |
|
||||
| `{{bowm}}` | Date of the beginning of the week (when week starts on Monday) based on the settings format | |
|
||||
| `{{bows}}` | Date of the beginning of the week (when week starts on Sunday) based on the settings format | |
|
||||
|
||||
# Searching
|
||||
|
||||
@@ -411,7 +413,7 @@ Please see the guide for information on how to contribute to the development of
|
||||
Joplin is currently available in the languages below. If you would like to contribute a **new translation**, it is quite straightforward, please follow these steps:
|
||||
|
||||
- [Download Poedit](https://poedit.net/), the translation editor, and install it.
|
||||
- [Download the file to be translated](https://raw.githubusercontent.com/laurent22/joplin/dev/packages/app-cli/locales/joplin.pot).
|
||||
- [Download the file to be translated](https://raw.githubusercontent.com/laurent22/joplin/dev/packages/tools/locales/joplin.pot).
|
||||
- In Poedit, open this .pot file, go into the Catalog menu and click Configuration. Change "Country" and "Language" to your own country and language.
|
||||
- From then you can translate the file.
|
||||
- Once it is done, please [open a pull request](https://github.com/laurent22/joplin/pulls) and add the file to it.
|
||||
|
||||
@@ -415,7 +415,7 @@ https://github.com/laurent22/joplin/blob/dev/readme/api/get_started/plugins.md
|
||||
</code></pre>
|
||||
<p>Doing so should compile all the files into the <code>dist/</code> directory. This is from here that Joplin will load the plugin.</p>
|
||||
<h2>Testing the plugin<a name="testing-the-plugin" href="#testing-the-plugin" class="heading-anchor">🔗</a></h2>
|
||||
<p>In order to test the plugin, you might want to run Joplin in <a href="https://github.com/laurent22/joplin/blob/dev/readme/api/references/development_mode/">Development Mode</a>. Doing so means that Joplin will run using a different profile, so you can experiment with the plugin without risking to accidentally change or delete your data.</p>
|
||||
<p>In order to test the plugin, you might want to run Joplin in <a href="https://joplinapp.org/api/references/development_mode/">Development Mode</a>. Doing so means that Joplin will run using a different profile, so you can experiment with the plugin without risking to accidentally change or delete your data.</p>
|
||||
<p>Finally, in order to test the plugin, open the Setting screen, then navigate the the <strong>Plugins</strong> section, and add the plugin path in the <strong>Development plugins</strong> text field. For example, if your plugin project path is <code>/home/user/src/joplin-plugin</code>, add this in the text field.</p>
|
||||
<p>Restart the app, and Joplin should load the plugin and execute its <code>onStart</code> handler. If all went well you should see the test message in the plugin console: "Test plugin started!".</p>
|
||||
<h1>Next steps<a name="next-steps" href="#next-steps" class="heading-anchor">🔗</a></h1>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -69,6 +69,15 @@
|
||||
<div class="lead">
|
||||
<p>This is the main entry point to the Joplin API. You can access various services using the provided accessors.</p>
|
||||
</div>
|
||||
<p><strong>This is a beta API</strong></p>
|
||||
<p>Please note that the plugin API is relatively new and should be considered Beta state. Besides possible bugs, what it means is that there might be necessary breaking changes from one version to the next. Whenever such change is needed, best effort will be done to:</p>
|
||||
<ul>
|
||||
<li>Maintain backward compatibility;</li>
|
||||
<li>When possible, deprecate features instead of removing them;</li>
|
||||
<li>Document breaking changes in the changelog;</li>
|
||||
</ul>
|
||||
<p>So if you are developing a plugin, please keep an eye on the changelog as everything will be in there with information about how to update your code. There won't be any major API rewrite or architecture changes, but possibly small tweaks like function signature change, type change, etc.</p>
|
||||
<p>Eventually, the plugin API will be versioned to make this process smoother.</p>
|
||||
</div>
|
||||
</section>
|
||||
<!--
|
||||
@@ -344,6 +353,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -291,6 +291,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -345,6 +345,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -244,6 +244,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -281,6 +281,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -372,6 +372,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -302,6 +302,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -68,8 +68,9 @@
|
||||
<div class="tsd-comment tsd-typography">
|
||||
<div class="lead">
|
||||
<p>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 <code>setHtml</code> method.
|
||||
Dialogs are hidden by default and you need to call <code>open()</code> to open them. Once the user clicks on a button, the <code>open</code> call will return and provide the button ID that was
|
||||
clicked on. 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.</p>
|
||||
Dialogs are hidden by default and you need to call <code>open()</code> to open them. Once the user clicks on a button, the <code>open</code> call will return an object indicating what button was clicked
|
||||
on. If your HTML content included one or more form, a <code>formData</code> 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.</p>
|
||||
</div>
|
||||
<p><a href="https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog">View the demo plugin</a></p>
|
||||
</div>
|
||||
@@ -136,7 +137,7 @@
|
||||
<a name="open" class="tsd-anchor"></a>
|
||||
<h3>open</h3>
|
||||
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class">
|
||||
<li class="tsd-signature tsd-kind-icon">open<span class="tsd-signature-symbol">(</span>handle<span class="tsd-signature-symbol">: </span><a href="../globals.html#viewhandle" class="tsd-signature-type">ViewHandle</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><a href="../globals.html#buttonid" class="tsd-signature-type">ButtonId</a><span class="tsd-signature-symbol">></span></li>
|
||||
<li class="tsd-signature tsd-kind-icon">open<span class="tsd-signature-symbol">(</span>handle<span class="tsd-signature-symbol">: </span><a href="../globals.html#viewhandle" class="tsd-signature-type">ViewHandle</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><a href="../interfaces/dialogresult.html" class="tsd-signature-type">DialogResult</a><span class="tsd-signature-symbol">></span></li>
|
||||
</ul>
|
||||
<ul class="tsd-descriptions">
|
||||
<li class="tsd-description">
|
||||
@@ -154,7 +155,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
<!-- JOPLINCHANGE
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><a href="../globals.html#buttonid" class="tsd-signature-type">ButtonId</a><span class="tsd-signature-symbol">></span></h4>
|
||||
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol"><</span><a href="../interfaces/dialogresult.html" class="tsd-signature-type">DialogResult</a><span class="tsd-signature-symbol">></span></h4>
|
||||
|
||||
|
||||
-->
|
||||
@@ -358,6 +359,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -230,6 +230,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -231,6 +231,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -327,6 +327,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -227,6 +227,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -378,6 +378,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -219,6 +219,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -186,6 +186,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -186,6 +186,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -241,6 +241,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -230,6 +230,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -196,6 +196,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="../interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
<li class="tsd-kind-interface"><a href="interfaces/buttonspec.html" class="tsd-kind-icon">Button<wbr>Spec</a></li>
|
||||
<li class="tsd-kind-interface"><a href="interfaces/command.html" class="tsd-kind-icon">Command</a></li>
|
||||
<li class="tsd-kind-interface"><a href="interfaces/createmenuitemoptions.html" class="tsd-kind-icon">Create<wbr>Menu<wbr>Item<wbr>Options</a></li>
|
||||
<li class="tsd-kind-interface"><a href="interfaces/dialogresult.html" class="tsd-kind-icon">Dialog<wbr>Result</a></li>
|
||||
<li class="tsd-kind-interface"><a href="interfaces/editorcommand.html" class="tsd-kind-icon">Editor<wbr>Command</a></li>
|
||||
<li class="tsd-kind-interface"><a href="interfaces/exportcontext.html" class="tsd-kind-icon">Export<wbr>Context</a></li>
|
||||
<li class="tsd-kind-interface"><a href="interfaces/exportmodule.html" class="tsd-kind-icon">Export<wbr>Module</a></li>
|
||||
@@ -234,6 +235,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -146,6 +146,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="interfaces/createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="interfaces/dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="interfaces/editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -228,6 +228,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -318,6 +318,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -187,6 +187,9 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="after-current">
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
272
docs/api/references/plugin_api/interfaces/dialogresult.html
Normal file
272
docs/api/references/plugin_api/interfaces/dialogresult.html
Normal file
@@ -0,0 +1,272 @@
|
||||
<!doctype html>
|
||||
<html class="default no-js">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>DialogResult | Joplin Plugin API Documentation</title>
|
||||
<meta name="description" content="Documentation for Joplin Plugin API Documentation">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../assets/css/main.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="tsd-page-toolbar">
|
||||
<div class="container">
|
||||
<div class="table-wrap">
|
||||
<div class="table-cell" id="tsd-search" data-index="../assets/js/search.json" data-base="..">
|
||||
<div class="field">
|
||||
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
|
||||
<input id="tsd-search-field" type="text" />
|
||||
</div>
|
||||
<ul class="results">
|
||||
<li class="state loading">Preparing search index...</li>
|
||||
<li class="state failure">The search index is not available</li>
|
||||
</ul>
|
||||
<a href="../classes/joplin.html" class="title">Joplin Plugin API Documentation</a>
|
||||
</div>
|
||||
<div class="table-cell" id="tsd-widgets">
|
||||
<div id="tsd-filter">
|
||||
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
|
||||
<div class="tsd-filter-group">
|
||||
<div class="tsd-select" id="tsd-filter-visibility">
|
||||
<span class="tsd-select-label">All</span>
|
||||
<ul class="tsd-select-list">
|
||||
<li data-value="public">Public</li>
|
||||
<li data-value="protected">Public/Protected</li>
|
||||
<li data-value="private" class="selected">All</li>
|
||||
</ul>
|
||||
</div>
|
||||
<input type="checkbox" id="tsd-filter-inherited" checked />
|
||||
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tsd-page-title">
|
||||
<div class="container">
|
||||
<ul class="tsd-breadcrumb">
|
||||
<!--
|
||||
<li>
|
||||
<a href="../globals.html">Globals</a>
|
||||
</li>
|
||||
-->
|
||||
<li>
|
||||
<a href="dialogresult.html">DialogResult</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h1><!-- Interface -->DialogResult</h1>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container container-main">
|
||||
<div class="row">
|
||||
<div class="col-8 col-content">
|
||||
<!--
|
||||
<section class="tsd-panel tsd-hierarchy">
|
||||
<h3>Hierarchy</h3>
|
||||
<ul class="tsd-hierarchy">
|
||||
<li>
|
||||
<span class="target">DialogResult</span>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
-->
|
||||
<section class="tsd-panel-group tsd-index-group">
|
||||
<h2>Index</h2>
|
||||
<section class="tsd-panel tsd-index-panel">
|
||||
<div class="tsd-index-content">
|
||||
<section class="tsd-index-section ">
|
||||
<h3>Properties</h3>
|
||||
<ul class="tsd-index-list">
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="dialogresult.html#formdata" class="tsd-kind-icon">form<wbr>Data</a></li>
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><a href="dialogresult.html#id" class="tsd-kind-icon">id</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section class="tsd-panel-group tsd-member-group ">
|
||||
<h2>Properties</h2>
|
||||
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
|
||||
<a name="formdata" class="tsd-anchor"></a>
|
||||
<h3><span class="tsd-flag ts-flagOptional">Optional</span> form<wbr>Data</h3>
|
||||
<div class="tsd-signature tsd-kind-icon">form<wbr>Data<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span></div>
|
||||
<aside class="tsd-sources">
|
||||
</aside>
|
||||
</section>
|
||||
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
|
||||
<a name="id" class="tsd-anchor"></a>
|
||||
<h3>id</h3>
|
||||
<div class="tsd-signature tsd-kind-icon">id<span class="tsd-signature-symbol">:</span> <a href="../globals.html#buttonid" class="tsd-signature-type">ButtonId</a></div>
|
||||
<aside class="tsd-sources">
|
||||
</aside>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
|
||||
<!--
|
||||
<nav class="tsd-navigation primary">
|
||||
<ul>
|
||||
<li class="globals ">
|
||||
<a href="../globals.html"><em>Globals</em></a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
-->
|
||||
<nav class="tsd-navigation secondary menu-sticky">
|
||||
<ul class="before-current">
|
||||
<li class=" tsd-kind-enum">
|
||||
<a href="../enums/contentscripttype.html" class="tsd-kind-icon">ContentScriptType</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-enum">
|
||||
<a href="../enums/filesystemitem.html" class="tsd-kind-icon">FileSystemItem</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-enum">
|
||||
<a href="../enums/importmoduleoutputformat.html" class="tsd-kind-icon">ImportModuleOutputFormat</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-enum">
|
||||
<a href="../enums/menuitemlocation.html" class="tsd-kind-icon">MenuItemLocation</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-enum">
|
||||
<a href="../enums/settingitemtype.html" class="tsd-kind-icon">SettingItemType</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-enum">
|
||||
<a href="../enums/toolbarbuttonlocation.html" class="tsd-kind-icon">ToolbarButtonLocation</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplin.html" class="tsd-kind-icon">joplin</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplincommands.html" class="tsd-kind-icon">joplin.commands</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplindata.html" class="tsd-kind-icon">joplin.data</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplininterop.html" class="tsd-kind-icon">joplin.interop</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinplugins.html" class="tsd-kind-icon">joplin.plugins</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinsettings.html" class="tsd-kind-icon">joplin.settings</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinviews.html" class="tsd-kind-icon">joplin.views</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinviewsdialogs.html" class="tsd-kind-icon">joplin.views.dialogs</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinviewsmenuitems.html" class="tsd-kind-icon">joplin.views.menuItems</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinviewsmenus.html" class="tsd-kind-icon">joplin.views.menus</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinviewspanels.html" class="tsd-kind-icon">joplin.views.panels</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinviewstoolbarbuttons.html" class="tsd-kind-icon">joplin.views.toolbarButtons</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-class">
|
||||
<a href="../classes/joplinworkspace.html" class="tsd-kind-icon">joplin.workspace</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="buttonspec.html" class="tsd-kind-icon">ButtonSpec</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="command.html" class="tsd-kind-icon">Command</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="current">
|
||||
<li class="current tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
<ul>
|
||||
<li class=" tsd-kind-property tsd-parent-kind-interface">
|
||||
<a href="dialogresult.html#formdata" class="tsd-kind-icon">form<wbr>Data</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-property tsd-parent-kind-interface">
|
||||
<a href="dialogresult.html#id" class="tsd-kind-icon">id</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="after-current">
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="exportcontext.html" class="tsd-kind-icon">ExportContext</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="exportmodule.html" class="tsd-kind-icon">ExportModule</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="exportoptions.html" class="tsd-kind-icon">ExportOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="importcontext.html" class="tsd-kind-icon">ImportContext</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="importmodule.html" class="tsd-kind-icon">ImportModule</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="menuitem.html" class="tsd-kind-icon">MenuItem</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="script.html" class="tsd-kind-icon">Script</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="settingitem.html" class="tsd-kind-icon">SettingItem</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="settingsection.html" class="tsd-kind-icon">SettingSection</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-type-alias">
|
||||
<a href="../globals.html#buttonid" class="tsd-kind-icon">ButtonId</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-type-alias">
|
||||
<a href="../globals.html#path" class="tsd-kind-icon">Path</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-type-alias">
|
||||
<a href="../globals.html#viewhandle" class="tsd-kind-icon">ViewHandle</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- JOPLINCHANGE
|
||||
<footer class="with-border-bottom">
|
||||
<div class="container">
|
||||
<h2>Legend</h2>
|
||||
<div class="tsd-legend-group">
|
||||
<ul class="tsd-legend">
|
||||
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
|
||||
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
|
||||
</ul>
|
||||
<ul class="tsd-legend">
|
||||
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
|
||||
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<div class="container tsd-generator">
|
||||
<p>Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p>
|
||||
</div>
|
||||
-->
|
||||
<div class="overlay"></div>
|
||||
<script src="../assets/js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -186,6 +186,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="current">
|
||||
<li class="current tsd-kind-interface">
|
||||
|
||||
@@ -199,6 +199,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -386,6 +386,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -218,6 +218,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -194,6 +194,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -288,6 +288,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -223,6 +223,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -195,6 +195,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -282,6 +282,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -202,6 +202,9 @@
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="createmenuitemoptions.html" class="tsd-kind-icon">CreateMenuItemOptions</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="dialogresult.html" class="tsd-kind-icon">DialogResult</a>
|
||||
</li>
|
||||
<li class=" tsd-kind-interface">
|
||||
<a href="editorcommand.html" class="tsd-kind-icon">EditorCommand</a>
|
||||
</li>
|
||||
|
||||
@@ -433,19 +433,39 @@ for (let portToTest = 41184; portToTest <= 41194; portToTest++) {
|
||||
</code></pre>
|
||||
<p>By default API results will contain the following fields: <strong>id</strong>, <strong>parent_id</strong>, <strong>title</strong></p>
|
||||
<h1>Pagination<a name="pagination" href="#pagination" class="heading-anchor">🔗</a></h1>
|
||||
<p>All API calls that return multiple results will be paginated. The actual results will be under the <code>items</code> key, and if there are more results, there will also be a <code>cursor</code> key, which allows you to fetch the next results. If the <code>cursor</code> key is not present, it means you have reached the end of the data set.</p>
|
||||
<p>All API calls that return multiple results will be paginated and will have the following structure:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Always present?</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>items</code></td>
|
||||
<td>Yes</td>
|
||||
<td>The array of items you have requested.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>has_more</code></td>
|
||||
<td>Yes</td>
|
||||
<td>If <code>true</code>, there are more items after this page. If <code>false</code>, it means you have reached the end of the data set.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>You can specify how the results should be sorted using the <code>order_by</code> and <code>order_dir</code> query parameters, and you can specify the number of items to be returned using the <code>limit</code> parameter (the maximum being 100 items).</p>
|
||||
<p>The following call for example will initiate a request to fetch all the notes, 10 at a time, and sorted by "updated_time" ascending:</p>
|
||||
<pre><code>curl http://localhost:41184/notes?order_by=updated_time&order_dir=ASC&limit=10
|
||||
</code></pre>
|
||||
<p>This will return a result like this</p>
|
||||
<pre><code>{ "items": [ /* 10 notes */ ], "cursor": "somecursor" }
|
||||
<pre><code>{ "items": [ /* 10 notes */ ], "has_more": true }
|
||||
</code></pre>
|
||||
<p>Then you will resume fetching the results using this query:</p>
|
||||
<pre><code>curl http://localhost:41184/notes?cursor=somecursor
|
||||
<pre><code>curl http://localhost:41184/notes?order_by=updated_time&order_dir=ASC&limit=10&page=2
|
||||
</code></pre>
|
||||
<p>Note that you only need to pass the cursor to the next request, as it will continue the fetching process using the same parameters you initially provided.</p>
|
||||
<p>Eventually you will get some results that do not contain a "cursor" paramater, at which point you will have retrieved all the results</p>
|
||||
<p>Eventually you will get some results that do not contain an "has_more" paramater, at which point you will have retrieved all the results</p>
|
||||
<p>As an example the pseudo-code below could be used to fetch all the notes:</p>
|
||||
<pre><code class="language-javascript">
|
||||
async function fetchJson(url) {
|
||||
@@ -453,15 +473,11 @@ async function fetchJson(url) {
|
||||
}
|
||||
|
||||
async function fetchAllNotes() {
|
||||
let query = '';
|
||||
const url = 'http://localhost:41184/notes';
|
||||
|
||||
let pageNum = 1;
|
||||
do {
|
||||
const response = await fetchJson(url + query);
|
||||
console.info('Printing notes:');
|
||||
console.info(response.items);
|
||||
query = '?cursor' + response.cursor;
|
||||
} while (response.cursor)
|
||||
const response = await fetchJson((http://localhost:41184/notes?page=' + pageNum++);
|
||||
console.info('Printing notes:', response.items);
|
||||
} while (response.has_more)
|
||||
}
|
||||
</code></pre>
|
||||
<h1>Error handling<a name="error-handling" href="#error-handling" class="heading-anchor">🔗</a></h1>
|
||||
@@ -916,6 +932,8 @@ async function fetchAllNotes() {
|
||||
<p>Gets resource with ID :id</p>
|
||||
<h2>GET /resources/:id/file<a name="get-resources-id-file" href="#get-resources-id-file" class="heading-anchor">🔗</a></h2>
|
||||
<p>Gets the actual file associated with this resource.</p>
|
||||
<h2>GET /resources/:id/notes<a name="get-resources-id-notes" href="#get-resources-id-notes" class="heading-anchor">🔗</a></h2>
|
||||
<p>Gets the notes (IDs) associated with a resource.</p>
|
||||
<h2>POST /resources<a name="post-resources" href="#post-resources" class="heading-anchor">🔗</a></h2>
|
||||
<p>Creates a new resource</p>
|
||||
<p>Creating a new resource is special because you also need to upload the file. Unlike other API calls, this one must have the "multipart/form-data" Content-Type. The file data must be passed to the "data" form field, and the other properties to the "props" form field. An example of a valid call with cURL would be:</p>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -512,7 +512,7 @@ https://github.com/laurent22/joplin/blob/dev/README.md
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center"><img width="50" src="https://avatars2.githubusercontent.com/u/1307332?s=96&v=4"/></br><a href="https://github.com/dbrandonjohnson">Brandon Johnson</a></td>
|
||||
<td style="text-align:center"></td>
|
||||
<td style="text-align:center"><img width="50" src="https://avatars1.githubusercontent.com/u/3061769?s=96&v=4"/></br><a href="https://github.com/c-nagy">@cnagy</a></td>
|
||||
<td style="text-align:center"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -682,6 +682,16 @@ Details:
|
||||
<td>Current date and/or time formatted based on a supplied string (using <a href="https://momentjs.com/">moment.js</a> formatting)</td>
|
||||
<td><code>{{#custom_datetime}}M d{{/custom_datetime}}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{{bowm}}</code></td>
|
||||
<td>Date of the beginning of the week (when week starts on Monday) based on the settings format</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>{{bows}}</code></td>
|
||||
<td>Date of the beginning of the week (when week starts on Sunday) based on the settings format</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h1>Searching<a name="searching" href="#searching" class="heading-anchor">🔗</a></h1>
|
||||
@@ -854,7 +864,7 @@ Eg. <code>:search -- "-tag:tag1"</code>.</p>
|
||||
<p>Joplin is currently available in the languages below. If you would like to contribute a <strong>new translation</strong>, it is quite straightforward, please follow these steps:</p>
|
||||
<ul>
|
||||
<li><a href="https://poedit.net/">Download Poedit</a>, the translation editor, and install it.</li>
|
||||
<li><a href="https://raw.githubusercontent.com/laurent22/joplin/dev/packages/app-cli/locales/joplin.pot">Download the file to be translated</a>.</li>
|
||||
<li><a href="https://raw.githubusercontent.com/laurent22/joplin/dev/packages/tools/locales/joplin.pot">Download the file to be translated</a>.</li>
|
||||
<li>In Poedit, open this .pot file, go into the Catalog menu and click Configuration. Change "Country" and "Language" to your own country and language.</li>
|
||||
<li>From then you can translate the file.</li>
|
||||
<li>Once it is done, please <a href="https://github.com/laurent22/joplin/pulls">open a pull request</a> and add the file to it.</li>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,11 @@
|
||||
"files.exclude": {
|
||||
"lerna-debug.log": true,
|
||||
"_mydocs/mdtest/": true,
|
||||
"./packages/lib/plugin_types": true,
|
||||
"_releases/": true,
|
||||
"_vieux/": true,
|
||||
".gitignore": true,
|
||||
".eslintignore": true,
|
||||
"./packages/app-cli/**/*.*~": true,
|
||||
"./packages/app-cli/**/*.mo": true,
|
||||
"./packages/app-cli/**/build/": true,
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
"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/",
|
||||
"buildTranslations": "node packages/tools/build-translation.js",
|
||||
"buildTranslations": "npm run tsc && node packages/tools/build-translation.js",
|
||||
"buildWebsite": "npm run buildApiDoc && node ./packages/tools/build-website.js && npm run buildPluginDoc",
|
||||
"clean": "lerna clean -y && lerna run clean",
|
||||
"generatePluginTypes": "rm -rf ./plugin_types && node node_modules/typescript/bin/tsc --declaration --declarationDir ./plugin_types --project tsconfig.json",
|
||||
"generateDatabaseTypes": "node packages/tools/generate-database-types",
|
||||
"linkChecker": "linkchecker https://joplinapp.org",
|
||||
"linter-ci": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||
"linter-precommit": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||
@@ -26,6 +26,8 @@
|
||||
"releaseDesktop": "node packages/tools/release-electron.js",
|
||||
"setupNewRelease": "node ./packages/tools/setupNewRelease",
|
||||
"tsc": "lerna run tsc --stream --parallel",
|
||||
"test": "lerna run test --stream",
|
||||
"test-ci": "lerna run test-ci --stream",
|
||||
"updateIgnored": "gulp updateIgnoredTypeScriptBuild",
|
||||
"watch": "lerna run watch --stream --parallel"
|
||||
},
|
||||
|
||||
@@ -117,7 +117,12 @@ class Command extends BaseCommand {
|
||||
|
||||
lines.push('# Pagination');
|
||||
lines.push('');
|
||||
lines.push('All API calls that return multiple results will be paginated. The actual results will be under the `items` key, and if there are more results, there will also be a `cursor` key, which allows you to fetch the next results. If the `cursor` key is not present, it means you have reached the end of the data set.');
|
||||
lines.push('All API calls that return multiple results will be paginated and will have the following structure:');
|
||||
lines.push('');
|
||||
lines.push('Key | Always present? | Description');
|
||||
lines.push('--- | --- | ---');
|
||||
lines.push('`items` | Yes | The array of items you have requested.');
|
||||
lines.push('`has_more` | Yes | If `true`, there are more items after this page. If `false`, it means you have reached the end of the data set.');
|
||||
lines.push('');
|
||||
lines.push('You can specify how the results should be sorted using the `order_by` and `order_dir` query parameters, and you can specify the number of items to be returned using the `limit` parameter (the maximum being 100 items).');
|
||||
lines.push('');
|
||||
@@ -127,15 +132,13 @@ class Command extends BaseCommand {
|
||||
lines.push('');
|
||||
lines.push('This will return a result like this');
|
||||
lines.push('');
|
||||
lines.push('\t{ "items": [ /* 10 notes */ ], "cursor": "somecursor" }');
|
||||
lines.push('\t{ "items": [ /* 10 notes */ ], "has_more": true }');
|
||||
lines.push('');
|
||||
lines.push('Then you will resume fetching the results using this query:');
|
||||
lines.push('');
|
||||
lines.push('\tcurl http://localhost:41184/notes?cursor=somecursor');
|
||||
lines.push('\tcurl http://localhost:41184/notes?order_by=updated_time&order_dir=ASC&limit=10&page=2');
|
||||
lines.push('');
|
||||
lines.push('Note that you only need to pass the cursor to the next request, as it will continue the fetching process using the same parameters you initially provided.');
|
||||
lines.push('');
|
||||
lines.push('Eventually you will get some results that do not contain a "cursor" paramater, at which point you will have retrieved all the results');
|
||||
lines.push('Eventually you will get some results that do not contain an "has_more" paramater, at which point you will have retrieved all the results');
|
||||
lines.push('');
|
||||
lines.push('As an example the pseudo-code below could be used to fetch all the notes:');
|
||||
lines.push('');
|
||||
@@ -146,15 +149,11 @@ async function fetchJson(url) {
|
||||
}
|
||||
|
||||
async function fetchAllNotes() {
|
||||
let query = '';
|
||||
const url = 'http://localhost:41184/notes';
|
||||
|
||||
let pageNum = 1;
|
||||
do {
|
||||
const response = await fetchJson(url + query);
|
||||
console.info('Printing notes:');
|
||||
console.info(response.items);
|
||||
query = '?cursor' + response.cursor;
|
||||
} while (response.cursor)
|
||||
const response = await fetchJson((http://localhost:41184/notes?page=' + pageNum++);
|
||||
console.info('Printing notes:', response.items);
|
||||
} while (response.has_more)
|
||||
}`);
|
||||
lines.push('```');
|
||||
lines.push('');
|
||||
|
||||
@@ -6,12 +6,12 @@ import executeSandboxCall from '@joplin/lib/services/plugins/utils/executeSandbo
|
||||
import Global from '@joplin/lib/services/plugins/api/Global';
|
||||
import mapEventHandlersToIds, { EventHandlers } from '@joplin/lib/services/plugins/utils/mapEventHandlersToIds';
|
||||
|
||||
function createConsoleWrapper(pluginId:string) {
|
||||
const wrapper:any = {};
|
||||
function createConsoleWrapper(pluginId: string) {
|
||||
const wrapper: any = {};
|
||||
|
||||
for (const n in console) {
|
||||
if (!console.hasOwnProperty(n)) continue;
|
||||
wrapper[n] = (...args:any[]) => {
|
||||
wrapper[n] = (...args: any[]) => {
|
||||
const newArgs = args.slice();
|
||||
newArgs.splice(0, 0, `Plugin "${pluginId}":`);
|
||||
return (console as any)[n](...newArgs);
|
||||
@@ -30,7 +30,7 @@ function createConsoleWrapper(pluginId:string) {
|
||||
|
||||
export default class PluginRunner extends BasePluginRunner {
|
||||
|
||||
private eventHandlers_:EventHandlers = {};
|
||||
private eventHandlers_: EventHandlers = {};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@@ -38,13 +38,13 @@ export default class PluginRunner extends BasePluginRunner {
|
||||
this.eventHandler = this.eventHandler.bind(this);
|
||||
}
|
||||
|
||||
private async eventHandler(eventHandlerId:string, args:any[]) {
|
||||
private async eventHandler(eventHandlerId: string, args: any[]) {
|
||||
const cb = this.eventHandlers_[eventHandlerId];
|
||||
return cb(...args);
|
||||
}
|
||||
|
||||
private newSandboxProxy(pluginId:string, sandbox:Global) {
|
||||
const target = async (path:string, args:any[]) => {
|
||||
private newSandboxProxy(pluginId: string, sandbox: Global) {
|
||||
const target = async (path: string, args: any[]) => {
|
||||
return executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
|
||||
};
|
||||
|
||||
@@ -54,8 +54,8 @@ export default class PluginRunner extends BasePluginRunner {
|
||||
};
|
||||
}
|
||||
|
||||
async run(plugin:Plugin, sandbox:Global):Promise<void> {
|
||||
return new Promise((resolve:Function, reject:Function) => {
|
||||
async run(plugin: Plugin, sandbox: Global): Promise<void> {
|
||||
return new Promise((resolve: Function, reject: Function) => {
|
||||
const onStarted = () => {
|
||||
plugin.off('started', onStarted);
|
||||
resolve();
|
||||
|
||||
47
packages/app-cli/jest.config.js
Normal file
47
packages/app-cli/jest.config.js
Normal file
@@ -0,0 +1,47 @@
|
||||
module.exports = {
|
||||
testMatch: [
|
||||
'**/tests/**/*.js',
|
||||
// '**/tests/services_keychainService.js',
|
||||
// '**/tests/urlUtils.js',
|
||||
// '**/tests/models_BaseItem.js',
|
||||
// '**/tests/markdownUtils.js',
|
||||
// '**/tests/models_Resource.js',
|
||||
],
|
||||
testPathIgnorePatterns: [
|
||||
'/node_modules/',
|
||||
'/tests\\/support/',
|
||||
'/build/',
|
||||
'test-utils.js',
|
||||
'file_api_driver.js',
|
||||
],
|
||||
testEnvironment: 'node',
|
||||
setupFilesAfterEnv: ['./jest.setup.js'],
|
||||
};
|
||||
|
||||
|
||||
|
||||
// PASS tests/services_rest_Api.js (14.705 s)
|
||||
// PASS tests/services_SearchFilter.js (21.203 s)
|
||||
// PASS tests/services_InteropService.js (10.807 s)
|
||||
// PASS tests/reducer.js (17.398 s)
|
||||
// PASS tests/services_Revision.js (17.642 s)
|
||||
// PASS tests/feature_NoteHistory.js (31.448 s)
|
||||
// PASS tests/services_KeymapService.js
|
||||
// PASS tests/services_EncryptionService.js (9.258 s)
|
||||
// PASS tests/models_Note.js (10.59 s)
|
||||
// PASS tests/services_ResourceService.js (13.177 s)
|
||||
// PASS tests/models_Folder.js (11.468 s)
|
||||
// PASS tests/MdToHtml.js (5.242 s)
|
||||
// PASS tests/services_PluginService.js (5.456 s)
|
||||
// PASS tests/models_Note_CustomSortOrder.js (5.52 s)
|
||||
// PASS tests/feature_ShowAllNotes.js (13.567 s)
|
||||
// PASS tests/models_Setting.js
|
||||
// PASS tests/models_Tag.js (6.324 s)
|
||||
// PASS tests/services_keychainService.js
|
||||
// PASS tests/urlUtils.js
|
||||
// PASS tests/models_BaseItem.js
|
||||
// PASS tests/markdownUtils.js
|
||||
// (node:15679) UnhandledPromiseRejectionWarning: Error: {"title":"folder1"}: Fields have not been loaded yet
|
||||
// (node:15679) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To termi$ate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 31)
|
||||
// (node:15679) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
|
||||
// FAIL tests/models_Resource.js
|
||||
5
packages/app-cli/jest.setup.js
Normal file
5
packages/app-cli/jest.setup.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { afterEachCleanUp } = require('./tests/test-utils.js');
|
||||
|
||||
global.afterEach(async () => {
|
||||
await afterEachCleanUp();
|
||||
});
|
||||
3955
packages/app-cli/package-lock.json
generated
3955
packages/app-cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,8 @@
|
||||
"author": "Laurent Cozic",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "node node_modules/jasmine/bin/jasmine.js --fail-fast=true --config=tests/support/jasmine.json",
|
||||
"test-ci": "node node_modules/jasmine/bin/jasmine.js --config=tests/support/jasmine.json",
|
||||
"test": "jest --config=jest.config.js --runInBand --bail --forceExit",
|
||||
"test-ci": "jest --config=jest.config.js --runInBand --forceExit",
|
||||
"build": "gulp build",
|
||||
"start": "gulp build -L && node \"build/main.js\" --stack-trace-enabled --log-level debug --env dev",
|
||||
"tsc": "node node_modules/typescript/bin/tsc --project tsconfig.json",
|
||||
@@ -69,6 +69,7 @@
|
||||
"@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"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('./tes
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
|
||||
function newTestMdToHtml(options:any = null) {
|
||||
function newTestMdToHtml(options: any = null) {
|
||||
options = {
|
||||
ResourceModel: {
|
||||
isResourceUrl: () => false,
|
||||
@@ -19,7 +19,7 @@ function newTestMdToHtml(options:any = null) {
|
||||
|
||||
describe('MdToHtml', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
@@ -39,7 +39,7 @@ describe('MdToHtml', function() {
|
||||
|
||||
// if (mdFilename !== 'sanitize_9.md') continue;
|
||||
|
||||
const mdToHtmlOptions:any = {
|
||||
const mdToHtmlOptions: any = {
|
||||
bodyOnly: true,
|
||||
};
|
||||
|
||||
@@ -83,7 +83,7 @@ describe('MdToHtml', function() {
|
||||
}));
|
||||
|
||||
it('should return enabled plugin assets', asyncTest(async () => {
|
||||
const pluginOptions:any = {};
|
||||
const pluginOptions: any = {};
|
||||
const pluginNames = MdToHtml.pluginNames();
|
||||
|
||||
for (const n of pluginNames) pluginOptions[n] = { enabled: false };
|
||||
|
||||
@@ -14,6 +14,11 @@ process.on('unhandledRejection', (reason, p) => {
|
||||
|
||||
const api = null;
|
||||
|
||||
// Adding empty test for Jest
|
||||
it('will pass', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
// NOTE: These tests work with S3 and memory driver, but not
|
||||
// with other targets like file system or Nextcloud.
|
||||
// All this is tested in an indirect way in tests/synchronizer
|
||||
|
||||
@@ -12,125 +12,125 @@ const makeTerm = (name, value, negated, quoted = false, wildcard = false) => {
|
||||
describe('filterParser should be correct filter for keyword', () => {
|
||||
it('title', () => {
|
||||
const searchString = 'title: something';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('title', 'something', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('title', 'something', false));
|
||||
});
|
||||
|
||||
it('negated title', () => {
|
||||
const searchString = '-title: something';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('title', 'something', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('title', 'something', true));
|
||||
});
|
||||
|
||||
it('body', () => {
|
||||
const searchString = 'body:something';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'something', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'something', false));
|
||||
});
|
||||
|
||||
it('negated body', () => {
|
||||
const searchString = '-body:something';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'something', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'something', true));
|
||||
});
|
||||
|
||||
it('title and body', () => {
|
||||
const searchString = 'title:testTitle body:testBody';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('title', 'testTitle', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'testBody', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('title', 'testTitle', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'testBody', false));
|
||||
});
|
||||
|
||||
it('title with multiple words', () => {
|
||||
const searchString = 'title:"word1 word2" body:testBody';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('title', 'word1', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('title', 'word2', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'testBody', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('title', 'word1', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('title', 'word2', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'testBody', false));
|
||||
});
|
||||
|
||||
it('body with multiple words', () => {
|
||||
const searchString = 'title:testTitle body:"word1 word2"';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('title', 'testTitle', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'word1', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'word2', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('title', 'testTitle', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'word1', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'word2', false));
|
||||
});
|
||||
|
||||
it('single word text', () => {
|
||||
const searchString = 'joplin';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('text', '"joplin"', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"joplin"', false));
|
||||
});
|
||||
|
||||
it('multi word text', () => {
|
||||
const searchString = 'scott joplin';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('text', '"scott"', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('text', '"joplin"', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"scott"', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"joplin"', false));
|
||||
});
|
||||
|
||||
it('negated word text', () => {
|
||||
const searchString = 'scott -joplin';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('text', '"scott"', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('text', '"joplin"', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"scott"', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"joplin"', true));
|
||||
});
|
||||
|
||||
it('phrase text search', () => {
|
||||
const searchString = '"scott joplin"';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('text', '"scott joplin"', false, true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('text', '"scott joplin"', false, true));
|
||||
});
|
||||
|
||||
it('multi word body', () => {
|
||||
const searchString = 'body:"foo bar"';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'foo', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('body', 'bar', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'foo', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('body', 'bar', false));
|
||||
});
|
||||
|
||||
it('negated tag queries', () => {
|
||||
const searchString = '-tag:mozart';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('tag', 'mozart', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('tag', 'mozart', true));
|
||||
});
|
||||
|
||||
|
||||
it('created after', () => {
|
||||
const searchString = 'created:20151218'; // YYYYMMDD
|
||||
expect(filterParser(searchString)).toContain(makeTerm('created', '20151218', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('created', '20151218', false));
|
||||
});
|
||||
|
||||
it('created before', () => {
|
||||
const searchString = '-created:20151218'; // YYYYMMDD
|
||||
expect(filterParser(searchString)).toContain(makeTerm('created', '20151218', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('created', '20151218', true));
|
||||
});
|
||||
|
||||
it('any', () => {
|
||||
const searchString = 'any:1 tag:123';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('any', '1', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('tag', '123', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('any', '1', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('tag', '123', false));
|
||||
});
|
||||
|
||||
it('wildcard tags', () => {
|
||||
let searchString = 'tag:*';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('tag', '%', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('tag', '%', false));
|
||||
|
||||
searchString = '-tag:*';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('tag', '%', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('tag', '%', true));
|
||||
|
||||
searchString = 'tag:bl*sphemy';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('tag', 'bl%sphemy', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('tag', 'bl%sphemy', false));
|
||||
|
||||
searchString = 'tag:"space travel"';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('tag', 'space travel', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('tag', 'space travel', false));
|
||||
});
|
||||
|
||||
it('wildcard notebooks', () => {
|
||||
const searchString = 'notebook:my*notebook';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('notebook', 'my%notebook', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('notebook', 'my%notebook', false));
|
||||
});
|
||||
|
||||
it('wildcard MIME types', () => {
|
||||
const searchString = 'resource:image/*';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('resource', 'image/%', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('resource', 'image/%', false));
|
||||
});
|
||||
|
||||
it('sourceurl', () => {
|
||||
let searchString = 'sourceurl:https://www.google.com';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('sourceurl', 'https://www.google.com', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('sourceurl', 'https://www.google.com', false));
|
||||
|
||||
searchString = 'sourceurl:https://www.google.com -sourceurl:https://www.facebook.com';
|
||||
expect(filterParser(searchString)).toContain(makeTerm('sourceurl', 'https://www.google.com', false));
|
||||
expect(filterParser(searchString)).toContain(makeTerm('sourceurl', 'https://www.facebook.com', true));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('sourceurl', 'https://www.google.com', false));
|
||||
expect(filterParser(searchString)).toContainEqual(makeTerm('sourceurl', 'https://www.facebook.com', true));
|
||||
});
|
||||
|
||||
it('handle invalid filters', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@ const { expectThrow } = require('./test-utils.js');
|
||||
|
||||
// On Windows, path.resolve is going to convert a path such as
|
||||
// /tmp/file.txt to c:\tmp\file.txt
|
||||
function platformPath(path:string) {
|
||||
function platformPath(path: string) {
|
||||
if (shim.isWindows()) {
|
||||
return `c:${path.replace(/\//g, '\\')}`;
|
||||
} else {
|
||||
|
||||
@@ -5,7 +5,7 @@ const { asyncTest } = require('./test-utils.js');
|
||||
const markdownUtils = require('@joplin/lib/markdownUtils').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at markdownUtils: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('markdownUtils', function() {
|
||||
|
||||
@@ -11,7 +11,7 @@ const BaseModel = require('@joplin/lib/BaseModel').default;
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at models_BaseItem: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
async function allItems() {
|
||||
|
||||
@@ -9,7 +9,7 @@ const BaseModel = require('@joplin/lib/BaseModel').default;
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at models_Folder: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
async function allItems() {
|
||||
|
||||
@@ -11,7 +11,7 @@ const ArrayUtils = require('@joplin/lib/ArrayUtils.js');
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at models_Note: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
async function allItems() {
|
||||
|
||||
@@ -11,7 +11,7 @@ const ArrayUtils = require('@joplin/lib/ArrayUtils.js');
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at models_Note_CustomSortOrder: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
async function allItems() {
|
||||
|
||||
@@ -3,7 +3,7 @@ import Setting from '@joplin/lib/models/Setting';
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('./test-utils.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at models_Setting: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('models_Setting', function() {
|
||||
|
||||
@@ -11,7 +11,7 @@ const BaseModel = require('@joplin/lib/BaseModel').default;
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at models_Tag: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('models_Tag', function() {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
// const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('../test-utils.js');
|
||||
|
||||
// describe('plugin_api_JoplinSetting', function() {
|
||||
|
||||
// beforeEach(async (done) => {
|
||||
// await setupDatabaseAndSynchronizer(1);
|
||||
// await switchClient(1);
|
||||
// done();
|
||||
// });
|
||||
|
||||
// it('should get and set plugin-specific values', asyncTest(async () => {
|
||||
// await
|
||||
// }));
|
||||
// });
|
||||
@@ -4,7 +4,7 @@ const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('../..
|
||||
|
||||
describe('services_plugins_sandboxProxy', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
@@ -12,13 +12,13 @@ describe('services_plugins_sandboxProxy', function() {
|
||||
|
||||
it('should create a new sandbox proxy', asyncTest(async () => {
|
||||
interface Result {
|
||||
path: string,
|
||||
args: any[],
|
||||
path: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
const results:Result[] = [];
|
||||
const results: Result[] = [];
|
||||
|
||||
const target:Target = (path:string, args:any[]) => {
|
||||
const target: Target = (path: string, args: any[]) => {
|
||||
results.push({ path, args });
|
||||
};
|
||||
|
||||
@@ -35,13 +35,13 @@ describe('services_plugins_sandboxProxy', function() {
|
||||
|
||||
it('should allow importing a namespace', asyncTest(async () => {
|
||||
interface Result {
|
||||
path: string,
|
||||
args: any[],
|
||||
path: string;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
const results:Result[] = [];
|
||||
const results: Result[] = [];
|
||||
|
||||
const target:Target = (path:string, args:any[]) => {
|
||||
const target: Target = (path: string, args: any[]) => {
|
||||
results.push({ path, args });
|
||||
};
|
||||
|
||||
|
||||
@@ -1,31 +1,33 @@
|
||||
import MenuUtils from '@joplin/lib/services/commands/MenuUtils';
|
||||
import ToolbarButtonUtils from '@joplin/lib/services/commands/ToolbarButtonUtils';
|
||||
import CommandService, { CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
import stateToWhenClauseContext from '@joplin/lib/services/commands/stateToWhenClauseContext';
|
||||
import KeymapService from '@joplin/lib/services/KeymapService';
|
||||
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('./test-utils.js');
|
||||
|
||||
interface TestCommand {
|
||||
declaration: CommandDeclaration,
|
||||
runtime: CommandRuntime,
|
||||
declaration: CommandDeclaration;
|
||||
runtime: CommandRuntime;
|
||||
}
|
||||
|
||||
function newService():CommandService {
|
||||
function newService(): CommandService {
|
||||
const service = new CommandService();
|
||||
const mockStore = {
|
||||
getState: () => {
|
||||
return {};
|
||||
},
|
||||
};
|
||||
service.initialize(mockStore, true);
|
||||
service.initialize(mockStore, true, stateToWhenClauseContext);
|
||||
return service;
|
||||
}
|
||||
|
||||
function createCommand(name:string, options:any):TestCommand {
|
||||
const declaration:CommandDeclaration = {
|
||||
function createCommand(name: string, options: any): TestCommand {
|
||||
const declaration: CommandDeclaration = {
|
||||
name: name,
|
||||
};
|
||||
|
||||
const runtime:CommandRuntime = {
|
||||
const runtime: CommandRuntime = {
|
||||
execute: options.execute,
|
||||
};
|
||||
|
||||
@@ -34,7 +36,7 @@ function createCommand(name:string, options:any):TestCommand {
|
||||
return { declaration, runtime };
|
||||
}
|
||||
|
||||
function registerCommand(service:CommandService, cmd:TestCommand) {
|
||||
function registerCommand(service: CommandService, cmd: TestCommand) {
|
||||
service.registerDeclaration(cmd.declaration);
|
||||
service.registerRuntime(cmd.declaration.name, cmd.runtime);
|
||||
}
|
||||
@@ -42,6 +44,9 @@ function registerCommand(service:CommandService, cmd:TestCommand) {
|
||||
describe('services_CommandService', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
KeymapService.destroyInstance();
|
||||
KeymapService.instance().initialize();
|
||||
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
@@ -51,7 +56,7 @@ describe('services_CommandService', function() {
|
||||
const service = newService();
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(service);
|
||||
|
||||
const executedCommands:string[] = [];
|
||||
const executedCommands: string[] = [];
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: () => {
|
||||
@@ -168,9 +173,9 @@ describe('services_CommandService', function() {
|
||||
execute: () => {},
|
||||
}));
|
||||
|
||||
const clickedCommands:string[] = [];
|
||||
const clickedCommands: string[] = [];
|
||||
|
||||
const onClick = (commandName:string) => {
|
||||
const onClick = (commandName: string) => {
|
||||
clickedCommands.push(commandName);
|
||||
};
|
||||
|
||||
@@ -230,7 +235,7 @@ describe('services_CommandService', function() {
|
||||
let propValue = null;
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: (_context:any, greeting:string) => {
|
||||
execute: (_context: any, greeting: string) => {
|
||||
propValue = greeting;
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -15,7 +15,7 @@ const SyncTargetRegistry = require('@joplin/lib/SyncTargetRegistry.js');
|
||||
const EncryptionService = require('@joplin/lib/services/EncryptionService.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at services_EncryptionService: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
let service = null;
|
||||
|
||||
@@ -12,14 +12,14 @@ const fs = require('fs-extra');
|
||||
const ArrayUtils = require('@joplin/lib/ArrayUtils');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at services_InteropService: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
function exportDir() {
|
||||
return `${__dirname}/export`;
|
||||
}
|
||||
|
||||
function fieldsEqual(model1:any, model2:any, fieldNames:string[]) {
|
||||
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}`);
|
||||
@@ -86,7 +86,7 @@ describe('services_InteropService', function() {
|
||||
await service.import({ path: filePath });
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.map((f:any) => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||
expect(allFolders.map((f: any) => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||
}));
|
||||
|
||||
it('should import folders, and only de-duplicate titles when needed', asyncTest(async () => {
|
||||
@@ -447,14 +447,14 @@ describe('services_InteropService', function() {
|
||||
sourcePath: '',
|
||||
};
|
||||
|
||||
const module:Module = {
|
||||
const module: Module = {
|
||||
type: ModuleType.Importer,
|
||||
description: 'Test Import Module',
|
||||
format: 'testing',
|
||||
fileExtensions: ['test'],
|
||||
isCustom: true,
|
||||
|
||||
onExec: async (context:CustomImportContext) => {
|
||||
onExec: async (context: CustomImportContext) => {
|
||||
result.hasBeenExecuted = true;
|
||||
result.sourcePath = context.sourcePath;
|
||||
},
|
||||
@@ -479,7 +479,7 @@ describe('services_InteropService', function() {
|
||||
|
||||
const filePath = `${exportDir()}/example.test`;
|
||||
|
||||
const result:any = {
|
||||
const result: any = {
|
||||
destPath: '',
|
||||
itemTypes: [],
|
||||
items: [],
|
||||
@@ -488,28 +488,28 @@ describe('services_InteropService', function() {
|
||||
closeCalled: false,
|
||||
};
|
||||
|
||||
const module:Module = {
|
||||
const module: Module = {
|
||||
type: ModuleType.Exporter,
|
||||
description: 'Test Export Module',
|
||||
format: 'testing',
|
||||
fileExtensions: ['test'],
|
||||
isCustom: true,
|
||||
|
||||
onInit: async (context:CustomExportContext) => {
|
||||
onInit: async (context: CustomExportContext) => {
|
||||
result.destPath = context.destPath;
|
||||
},
|
||||
|
||||
onProcessItem: async (_context:CustomExportContext, itemType:number, item:any) => {
|
||||
onProcessItem: async (_context: CustomExportContext, itemType: number, item: any) => {
|
||||
result.itemTypes.push(itemType);
|
||||
result.items.push(item);
|
||||
},
|
||||
|
||||
onProcessResource: async (_context:CustomExportContext, resource:any, filePath:string) => {
|
||||
onProcessResource: async (_context: CustomExportContext, resource: any, filePath: string) => {
|
||||
result.resources.push(resource);
|
||||
result.filePaths.push(filePath);
|
||||
},
|
||||
|
||||
onClose: async (_context:CustomExportContext) => {
|
||||
onClose: async (_context: CustomExportContext) => {
|
||||
result.closeCalled = true;
|
||||
},
|
||||
};
|
||||
@@ -524,7 +524,7 @@ describe('services_InteropService', function() {
|
||||
expect(result.destPath).toBe(filePath);
|
||||
expect(result.itemTypes.sort().join('_')).toBe('1_1_2_4');
|
||||
expect(result.items.length).toBe(4);
|
||||
expect(result.items.map((o:any) => o.title).sort().join('_')).toBe('folder1_note1_note2_photo.jpg');
|
||||
expect(result.items.map((o: any) => o.title).sort().join('_')).toBe('folder1_note1_note2_photo.jpg');
|
||||
expect(result.resources.length).toBe(1);
|
||||
expect(result.resources[0].title).toBe('photo.jpg');
|
||||
expect(result.filePaths.length).toBe(1);
|
||||
|
||||
@@ -9,7 +9,7 @@ const Note = require('@joplin/lib/models/Note');
|
||||
const Folder = require('@joplin/lib/models/Folder');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at services_PluginService: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
const testPluginDir = `${__dirname}/../tests/support/plugins`;
|
||||
@@ -44,6 +44,8 @@ describe('services_PluginService', function() {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/simple`]);
|
||||
|
||||
expect(() => service.pluginById('simple')).not.toThrowError();
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.length).toBe(1);
|
||||
expect(allFolders[0].title).toBe('my plugin folder');
|
||||
@@ -54,6 +56,12 @@ describe('services_PluginService', function() {
|
||||
expect(allNotes[0].parent_id).toBe(allFolders[0].id);
|
||||
}));
|
||||
|
||||
it('should load and run a simple plugin and handle trailing slash', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/simple/`]);
|
||||
expect(() => service.pluginById('simple')).not.toThrowError();
|
||||
}));
|
||||
|
||||
it('should load and run a plugin that uses external packages', asyncTest(async () => {
|
||||
const service = newPluginService();
|
||||
await service.loadAndRunPlugins([`${testPluginDir}/withExternalModules`]);
|
||||
@@ -79,7 +87,7 @@ describe('services_PluginService', function() {
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.length).toBe(2);
|
||||
expect(allFolders.map((f:any) => f.title).sort().join(', ')).toBe('multi - simple1, multi - simple2');
|
||||
expect(allFolders.map((f: any) => f.title).sort().join(', ')).toBe('multi - simple1, multi - simple2');
|
||||
}));
|
||||
|
||||
it('should load plugins from JS bundles', asyncTest(async () => {
|
||||
|
||||
@@ -15,7 +15,7 @@ const RevisionService = require('@joplin/lib/services/RevisionService.js');
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at services_Revision: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
describe('services_Revision', function() {
|
||||
|
||||
@@ -157,85 +157,88 @@ describe('services_SearchEngine', function() {
|
||||
expect(rows[1].id).toBe(n2.id);
|
||||
}));
|
||||
|
||||
it('should correctly weigh notes using BM25 and user_updated_time', asyncTest(async () => {
|
||||
await mockDate(2020, 9, 30, 50);
|
||||
const noteData = [
|
||||
{
|
||||
title: 'abc test2 test2',
|
||||
updated_time: 1601425064756,
|
||||
user_updated_time: 1601425064756,
|
||||
created_time: 1601425064756,
|
||||
user_created_time: 1601425064756,
|
||||
},
|
||||
{
|
||||
title: 'foo foo',
|
||||
updated_time: 1601425064758,
|
||||
user_updated_time: 1601425064758,
|
||||
created_time: 1601425064758,
|
||||
user_created_time: 1601425064758,
|
||||
},
|
||||
{
|
||||
title: 'dead beef',
|
||||
updated_time: 1601425064760,
|
||||
user_updated_time: 1601425064760,
|
||||
created_time: 1601425064760,
|
||||
user_created_time: 1601425064760,
|
||||
},
|
||||
{
|
||||
title: 'test2 bar',
|
||||
updated_time: 1601425064761,
|
||||
user_updated_time: 1601425064761,
|
||||
created_time: 1601425064761,
|
||||
user_created_time: 1601425064761,
|
||||
},
|
||||
{
|
||||
title: 'blah blah abc',
|
||||
updated_time: 1601425064763,
|
||||
user_updated_time: 1601425064763,
|
||||
created_time: 1601425064763,
|
||||
user_created_time: 1601425064763,
|
||||
},
|
||||
];
|
||||
// TODO: Need to update and replace jasmine.mockDate() calls with Jest
|
||||
// equivalent
|
||||
|
||||
const n0 = await Note.save(noteData[0], { autoTimestamp: false });
|
||||
const n1 = await Note.save(noteData[1], { autoTimestamp: false });
|
||||
const n2 = await Note.save(noteData[2], { autoTimestamp: false });
|
||||
const n3 = await Note.save(noteData[3], { autoTimestamp: false });
|
||||
const n4 = await Note.save(noteData[4], { autoTimestamp: false });
|
||||
restoreDate();
|
||||
await engine.syncTables();
|
||||
await mockDate(2020, 9, 30, 50);
|
||||
// it('should correctly weigh notes using BM25 and user_updated_time', asyncTest(async () => {
|
||||
// await mockDate(2020, 9, 30, 50);
|
||||
// const noteData = [
|
||||
// {
|
||||
// title: 'abc test2 test2',
|
||||
// updated_time: 1601425064756,
|
||||
// user_updated_time: 1601425064756,
|
||||
// created_time: 1601425064756,
|
||||
// user_created_time: 1601425064756,
|
||||
// },
|
||||
// {
|
||||
// title: 'foo foo',
|
||||
// updated_time: 1601425064758,
|
||||
// user_updated_time: 1601425064758,
|
||||
// created_time: 1601425064758,
|
||||
// user_created_time: 1601425064758,
|
||||
// },
|
||||
// {
|
||||
// title: 'dead beef',
|
||||
// updated_time: 1601425064760,
|
||||
// user_updated_time: 1601425064760,
|
||||
// created_time: 1601425064760,
|
||||
// user_created_time: 1601425064760,
|
||||
// },
|
||||
// {
|
||||
// title: 'test2 bar',
|
||||
// updated_time: 1601425064761,
|
||||
// user_updated_time: 1601425064761,
|
||||
// created_time: 1601425064761,
|
||||
// user_created_time: 1601425064761,
|
||||
// },
|
||||
// {
|
||||
// title: 'blah blah abc',
|
||||
// updated_time: 1601425064763,
|
||||
// user_updated_time: 1601425064763,
|
||||
// created_time: 1601425064763,
|
||||
// user_created_time: 1601425064763,
|
||||
// },
|
||||
// ];
|
||||
|
||||
let searchString = 'abc';
|
||||
let scores = calculateScore(searchString, noteData);
|
||||
let rows = await engine.search(searchString);
|
||||
// const n0 = await Note.save(noteData[0], { autoTimestamp: false });
|
||||
// const n1 = await Note.save(noteData[1], { autoTimestamp: false });
|
||||
// const n2 = await Note.save(noteData[2], { autoTimestamp: false });
|
||||
// const n3 = await Note.save(noteData[3], { autoTimestamp: false });
|
||||
// const n4 = await Note.save(noteData[4], { autoTimestamp: false });
|
||||
// restoreDate();
|
||||
// await engine.syncTables();
|
||||
// await mockDate(2020, 9, 30, 50);
|
||||
|
||||
expect(rows[0].weight).toEqual(scores[0]);
|
||||
expect(rows[1].weight).toEqual(scores[1]);
|
||||
// let searchString = 'abc';
|
||||
// let scores = calculateScore(searchString, noteData);
|
||||
// let rows = await engine.search(searchString);
|
||||
|
||||
// console.log(rows);
|
||||
// console.log(scores);
|
||||
// expect(rows[0].weight).toEqual(scores[0]);
|
||||
// expect(rows[1].weight).toEqual(scores[1]);
|
||||
|
||||
searchString = 'test2';
|
||||
scores = calculateScore(searchString, noteData);
|
||||
rows = await engine.search(searchString);
|
||||
// // console.log(rows);
|
||||
// // console.log(scores);
|
||||
|
||||
// console.log(rows);
|
||||
// console.log(scores);
|
||||
// searchString = 'test2';
|
||||
// scores = calculateScore(searchString, noteData);
|
||||
// rows = await engine.search(searchString);
|
||||
|
||||
expect(rows[0].weight).toEqual(scores[0]);
|
||||
expect(rows[1].weight).toEqual(scores[1]);
|
||||
// // console.log(rows);
|
||||
// // console.log(scores);
|
||||
|
||||
searchString = 'foo';
|
||||
scores = calculateScore(searchString, noteData);
|
||||
rows = await engine.search(searchString);
|
||||
// expect(rows[0].weight).toEqual(scores[0]);
|
||||
// expect(rows[1].weight).toEqual(scores[1]);
|
||||
|
||||
// console.log(rows);
|
||||
// console.log(scores);
|
||||
// searchString = 'foo';
|
||||
// scores = calculateScore(searchString, noteData);
|
||||
// rows = await engine.search(searchString);
|
||||
|
||||
expect(rows[0].weight).toEqual(scores[0]);
|
||||
await restoreDate();
|
||||
}));
|
||||
// // console.log(rows);
|
||||
// // console.log(scores);
|
||||
|
||||
// expect(rows[0].weight).toEqual(scores[0]);
|
||||
// await restoreDate();
|
||||
// }));
|
||||
|
||||
it('should tell where the results are found', asyncTest(async () => {
|
||||
const notes = [
|
||||
|
||||
@@ -16,7 +16,7 @@ const ResourceService = require('@joplin/lib/services/ResourceService').default;
|
||||
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
console.log('Unhandled Rejection at services_SearchFilter: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
let engine = null;
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
/* eslint prefer-const: 0*/
|
||||
|
||||
//
|
||||
// const time = require('@joplin/lib/time').default;
|
||||
// const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, asyncTest, db, synchronizer, fileApi, sleep, createNTestNotes, switchClient, createNTestFolders } = require('./test-utils.js');
|
||||
// const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine');
|
||||
// const Note = require('@joplin/lib/models/Note');
|
||||
// const Folder = require('@joplin/lib/models/Folder');
|
||||
// const Tag = require('@joplin/lib/models/Tag');
|
||||
// const ItemChange = require('@joplin/lib/models/ItemChange');
|
||||
// const Setting = require('@joplin/lib/models/Setting');
|
||||
// const Resource = require('@joplin/lib/models/Resource.js');
|
||||
// const shim = require('@joplin/lib/shim').default;
|
||||
// const ResourceService = require('@joplin/lib/services/ResourceService').default;
|
||||
|
||||
// process.on('unhandledRejection', (reason, p) => {
|
||||
// console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
// });
|
||||
|
||||
// let engine = null;
|
||||
|
||||
// const ids = (array) => array.map(a => a.id);
|
||||
|
||||
// describe('services_SearchFuzzy', function() {
|
||||
// beforeEach(async (done) => {
|
||||
// await setupDatabaseAndSynchronizer(1);
|
||||
// await switchClient(1);
|
||||
|
||||
// engine = new SearchEngine();
|
||||
// engine.setDb(db());
|
||||
|
||||
// Setting.setValue('db.fuzzySearchEnabled', 1);
|
||||
// done();
|
||||
// });
|
||||
|
||||
|
||||
// it('should return note almost matching title', asyncTest(async () => {
|
||||
// let rows;
|
||||
// const n1 = await Note.save({ title: 'If It Ain\'t Baroque, Don\'t Fix It' });
|
||||
// const n2 = await Note.save({ title: 'Important note' });
|
||||
|
||||
// await engine.syncTables();
|
||||
// rows = await engine.search('Broke', { fuzzy: false });
|
||||
// expect(rows.length).toBe(0);
|
||||
|
||||
// rows = await engine.search('Broke', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows[0].id).toBe(n1.id);
|
||||
|
||||
|
||||
// rows = await engine.search('title:Broke', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows[0].id).toBe(n1.id);
|
||||
|
||||
// rows = await engine.search('title:"Broke"', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows[0].id).toBe(n1.id);
|
||||
|
||||
// rows = await engine.search('Imprtant', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows[0].id).toBe(n2.id);
|
||||
// }));
|
||||
|
||||
|
||||
// it('should order results by min fuzziness', asyncTest(async () => {
|
||||
// let rows;
|
||||
// const n1 = await Note.save({ title: 'I demand you take me to him' });
|
||||
// const n2 = await Note.save({ title: 'He demanded an answer' });
|
||||
// const n3 = await Note.save({ title: 'Don\'t you make demands of me' });
|
||||
// const n4 = await Note.save({ title: 'No drama for me' });
|
||||
// const n5 = await Note.save({ title: 'Just minding my own business' });
|
||||
|
||||
// await engine.syncTables();
|
||||
// rows = await engine.search('demand', { fuzzy: false });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows[0].id).toBe(n1.id);
|
||||
|
||||
|
||||
// rows = await engine.search('demand', { fuzzy: true });
|
||||
// expect(rows.length).toBe(3);
|
||||
// expect(rows[0].id).toBe(n1.id);
|
||||
// expect(rows[1].id).toBe(n3.id);
|
||||
// expect(rows[2].id).toBe(n2.id);
|
||||
// }));
|
||||
|
||||
// it('should consider any:1', asyncTest(async () => {
|
||||
// let rows;
|
||||
// const n1 = await Note.save({ title: 'cat' });
|
||||
// const n2 = await Note.save({ title: 'cats' });
|
||||
// const n3 = await Note.save({ title: 'cot' });
|
||||
|
||||
// const n4 = await Note.save({ title: 'defenestrate' });
|
||||
// const n5 = await Note.save({ title: 'defenstrate' });
|
||||
// const n6 = await Note.save({ title: 'defenestrated' });
|
||||
|
||||
// const n7 = await Note.save({ title: 'he defenestrated the cat' });
|
||||
|
||||
// await engine.syncTables();
|
||||
|
||||
// rows = await engine.search('defenestrated cat', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
|
||||
// rows = await engine.search('any:1 defenestrated cat', { fuzzy: true });
|
||||
// expect(rows.length).toBe(7);
|
||||
// }));
|
||||
|
||||
// it('should leave phrase searches alone', asyncTest(async () => {
|
||||
// let rows;
|
||||
// const n1 = await Note.save({ title: 'abc def' });
|
||||
// const n2 = await Note.save({ title: 'def ghi' });
|
||||
// const n3 = await Note.save({ title: 'ghi jkl' });
|
||||
// const n4 = await Note.save({ title: 'def abc' });
|
||||
// const n5 = await Note.save({ title: 'mno pqr ghi jkl' });
|
||||
|
||||
// await engine.syncTables();
|
||||
|
||||
// rows = await engine.search('abc def', { fuzzy: true });
|
||||
// expect(rows.length).toBe(2);
|
||||
// expect(rows.map(r=>r.id)).toContain(n1.id);
|
||||
// expect(rows.map(r=>r.id)).toContain(n4.id);
|
||||
|
||||
// rows = await engine.search('"abc def"', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows.map(r=>r.id)).toContain(n1.id);
|
||||
|
||||
// rows = await engine.search('"ghi jkl"', { fuzzy: true });
|
||||
// expect(rows.length).toBe(2);
|
||||
// expect(rows.map(r=>r.id)).toContain(n3.id);
|
||||
// expect(rows.map(r=>r.id)).toContain(n5.id);
|
||||
|
||||
// rows = await engine.search('"ghi jkl" mno', { fuzzy: true });
|
||||
// expect(rows.length).toBe(1);
|
||||
// expect(rows.map(r=>r.id)).toContain(n5.id);
|
||||
|
||||
// rows = await engine.search('any:1 "ghi jkl" mno', { fuzzy: true });
|
||||
// expect(rows.length).toBe(2);
|
||||
// expect(rows.map(r=>r.id)).toContain(n3.id);
|
||||
// expect(rows.map(r=>r.id)).toContain(n5.id);
|
||||
// }));
|
||||
|
||||
// it('should leave wild card searches alone', asyncTest(async () => {
|
||||
// let rows;
|
||||
// const n1 = await Note.save({ title: 'abc def' });
|
||||
// const n2 = await Note.save({ title: 'abcc ghi' });
|
||||
// const n3 = await Note.save({ title: 'abccc ghi' });
|
||||
// const n4 = await Note.save({ title: 'abcccc ghi' });
|
||||
// const n5 = await Note.save({ title: 'wxy zzz' });
|
||||
|
||||
// await engine.syncTables();
|
||||
|
||||
// rows = await engine.search('abc*', { fuzzy: true });
|
||||
|
||||
// expect(rows.length).toBe(4);
|
||||
// expect(rows.map(r=>r.id)).toContain(n1.id);
|
||||
// expect(rows.map(r=>r.id)).toContain(n2.id);
|
||||
// expect(rows.map(r=>r.id)).toContain(n3.id);
|
||||
// expect(rows.map(r=>r.id)).toContain(n4.id);
|
||||
// }));
|
||||
|
||||
// });
|
||||
@@ -4,22 +4,24 @@ import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
const { db, asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
|
||||
|
||||
function describeIfCompatible(name:string, fn:any) {
|
||||
function describeIfCompatible(name: string, fn: any, elseFn: any) {
|
||||
if (['win32', 'darwin'].includes(shim.platformName())) {
|
||||
return describe(name, fn);
|
||||
} else {
|
||||
elseFn();
|
||||
}
|
||||
}
|
||||
|
||||
describeIfCompatible('services_KeychainService', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1, { keychainEnabled: true });
|
||||
await switchClient(1, { keychainEnabled: true });
|
||||
await Setting.deleteKeychainPasswords();
|
||||
done();
|
||||
});
|
||||
|
||||
afterEach(async (done:Function) => {
|
||||
afterEach(async (done: Function) => {
|
||||
await Setting.deleteKeychainPasswords();
|
||||
done();
|
||||
});
|
||||
@@ -91,4 +93,10 @@ describeIfCompatible('services_KeychainService', function() {
|
||||
}
|
||||
}));
|
||||
|
||||
}, () => {
|
||||
|
||||
it('will pass', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -2,15 +2,16 @@ import { PaginationOrderDir } from '@joplin/lib/models/utils/types';
|
||||
import Api, { RequestMethod } from '@joplin/lib/services/rest/Api';
|
||||
import shim from '@joplin/lib/shim';
|
||||
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('./test-utils.js');
|
||||
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync, db } = require('./test-utils.js');
|
||||
const Folder = require('@joplin/lib/models/Folder');
|
||||
const Resource = require('@joplin/lib/models/Resource');
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const Tag = require('@joplin/lib/models/Tag');
|
||||
const NoteTag = require('@joplin/lib/models/NoteTag');
|
||||
const ResourceService = require('@joplin/lib/services/ResourceService').default;
|
||||
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine');
|
||||
|
||||
async function msleep(ms:number) {
|
||||
async function msleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
shim.setTimeout(() => {
|
||||
resolve();
|
||||
@@ -18,7 +19,7 @@ async function msleep(ms:number) {
|
||||
});
|
||||
}
|
||||
|
||||
const createFolderForPagination = async (num:number, time:number) => {
|
||||
const createFolderForPagination = async (num: number, time: number) => {
|
||||
await Folder.save({
|
||||
title: `folder${num}`,
|
||||
updated_time: time,
|
||||
@@ -26,7 +27,16 @@ const createFolderForPagination = async (num:number, time:number) => {
|
||||
}, { autoTimestamp: false });
|
||||
};
|
||||
|
||||
let api:Api = null;
|
||||
const createNoteForPagination = async (num: number, time: number) => {
|
||||
await Note.save({
|
||||
title: `note${num}`,
|
||||
body: `noteBody${num}`,
|
||||
updated_time: time,
|
||||
created_time: time,
|
||||
}, { autoTimestamp: false });
|
||||
};
|
||||
|
||||
let api: Api = null;
|
||||
|
||||
describe('services_rest_Api', function() {
|
||||
|
||||
@@ -148,7 +158,7 @@ describe('services_rest_Api', function() {
|
||||
}));
|
||||
|
||||
it('should allow setting note properties', asyncTest(async () => {
|
||||
let response:any = null;
|
||||
let response: any = null;
|
||||
const f = await Folder.save({ title: 'mon carnet' });
|
||||
|
||||
response = await api.route(RequestMethod.POST, 'notes', null, JSON.stringify({
|
||||
@@ -353,22 +363,6 @@ describe('services_rest_Api', function() {
|
||||
expect(response.body).toBe('**Bold text**');
|
||||
}));
|
||||
|
||||
// it('should filter fields', asyncTest(async () => {
|
||||
// let f = api.fields_({ query: { fields: 'one,two' } } as any, []);
|
||||
// expect(f.length).toBe(2);
|
||||
// expect(f[0]).toBe('one');
|
||||
// expect(f[1]).toBe('two');
|
||||
|
||||
// f = api.fields_({ query: { fields: 'one ,, two ' } } as any, []);
|
||||
// expect(f.length).toBe(2);
|
||||
// expect(f[0]).toBe('one');
|
||||
// expect(f[1]).toBe('two');
|
||||
|
||||
// f = api.fields_({ query: { fields: ' ' } } as any, ['def']);
|
||||
// expect(f.length).toBe(1);
|
||||
// expect(f[0]).toBe('def');
|
||||
// }));
|
||||
|
||||
it('should handle tokens', asyncTest(async () => {
|
||||
api = new Api('mytoken');
|
||||
|
||||
@@ -513,82 +507,117 @@ describe('services_rest_Api', function() {
|
||||
await createFolderForPagination(4, 1004);
|
||||
|
||||
{
|
||||
const r1 = await api.route(RequestMethod.GET, 'folders', {
|
||||
const baseQuery = {
|
||||
fields: ['id', 'title', 'updated_time'],
|
||||
limit: 2,
|
||||
order_dir: PaginationOrderDir.ASC,
|
||||
order_by: 'updated_time',
|
||||
});
|
||||
};
|
||||
|
||||
const r1 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery });
|
||||
|
||||
expect(r1.has_more).toBe(true);
|
||||
expect(r1.items.length).toBe(2);
|
||||
expect(r1.items[0].title).toBe('folder1');
|
||||
expect(r1.items[1].title).toBe('folder2');
|
||||
|
||||
const r2 = await api.route(RequestMethod.GET, 'folders', {
|
||||
cursor: r1.cursor,
|
||||
});
|
||||
const r2 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery, page: 2 });
|
||||
|
||||
// The API currently doesn't check if there's effectively a
|
||||
// page of data after the current one. If the number of
|
||||
// returned items === limit, it sets `has_more` and the next
|
||||
// result set will be empty
|
||||
expect(r1.has_more).toBe(true);
|
||||
expect(r2.items.length).toBe(2);
|
||||
expect(r2.items[0].title).toBe('folder3');
|
||||
expect(r2.items[1].title).toBe('folder4');
|
||||
|
||||
const r3 = await api.route(RequestMethod.GET, 'folders', {
|
||||
cursor: r2.cursor,
|
||||
});
|
||||
const r3 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery, page: 3 });
|
||||
|
||||
expect(r3.items.length).toBe(0);
|
||||
expect(r3.cursor).toBe(undefined);
|
||||
expect(r3.has_more).toBe(undefined);
|
||||
}
|
||||
|
||||
{
|
||||
const r1 = await api.route(RequestMethod.GET, 'folders', {
|
||||
const baseQuery = {
|
||||
fields: ['id', 'title', 'updated_time'],
|
||||
limit: 3,
|
||||
order_dir: PaginationOrderDir.ASC,
|
||||
order_by: 'updated_time',
|
||||
});
|
||||
};
|
||||
|
||||
const r1 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery });
|
||||
|
||||
expect(r1.items.length).toBe(3);
|
||||
expect(r1.items[0].title).toBe('folder1');
|
||||
expect(r1.items[1].title).toBe('folder2');
|
||||
expect(r1.items[2].title).toBe('folder3');
|
||||
|
||||
const r2 = await api.route(RequestMethod.GET, 'folders', {
|
||||
cursor: r1.cursor,
|
||||
});
|
||||
const r2 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery, page: 2 });
|
||||
|
||||
expect(r2.items.length).toBe(1);
|
||||
expect(r2.items[0].title).toBe('folder4');
|
||||
expect(r2.cursor).toBe(undefined);
|
||||
expect(r2.has_more).toBe(undefined);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should paginate results and handle duplicate cursor field value', asyncTest(async () => {
|
||||
it('should paginate results and handle duplicate field values', asyncTest(async () => {
|
||||
// If, for example, ordering by updated_time, and two of the rows
|
||||
// have the same updated_time, it should make sure that the sort
|
||||
// order is stable and all results are correctly returned.
|
||||
await createFolderForPagination(1, 1001);
|
||||
await createFolderForPagination(2, 1002);
|
||||
await createFolderForPagination(3, 1002);
|
||||
await createFolderForPagination(4, 1003);
|
||||
|
||||
const r1 = await api.route(RequestMethod.GET, 'folders', {
|
||||
const baseQuery = {
|
||||
fields: ['id', 'title', 'updated_time'],
|
||||
limit: 2,
|
||||
order_dir: PaginationOrderDir.ASC,
|
||||
order_by: 'updated_time',
|
||||
});
|
||||
};
|
||||
|
||||
const r1 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery });
|
||||
|
||||
expect(r1.items.length).toBe(2);
|
||||
expect(r1.items[0].title).toBe('folder1');
|
||||
expect(['folder2', 'folder3'].includes(r1.items[1].title)).toBe(true);
|
||||
|
||||
const r2 = await api.route(RequestMethod.GET, 'folders', {
|
||||
cursor: r1.cursor,
|
||||
});
|
||||
const r2 = await api.route(RequestMethod.GET, 'folders', { ...baseQuery, page: 2 });
|
||||
|
||||
expect(r2.items.length).toBe(2);
|
||||
expect(r2.items[0].title).toBe(r1.items[1].title === 'folder2' ? 'folder3' : 'folder2');
|
||||
expect(r2.items[1].title).toBe('folder4');
|
||||
}));
|
||||
|
||||
it('should paginate results and return the requested fields only', asyncTest(async () => {
|
||||
await createNoteForPagination(1, 1001);
|
||||
await createNoteForPagination(2, 1002);
|
||||
await createNoteForPagination(3, 1003);
|
||||
|
||||
const baseQuery = {
|
||||
fields: ['id', 'title', 'body'],
|
||||
limit: 2,
|
||||
order_dir: PaginationOrderDir.ASC,
|
||||
order_by: 'updated_time',
|
||||
};
|
||||
|
||||
const r1 = await api.route(RequestMethod.GET, 'notes', { ...baseQuery });
|
||||
|
||||
expect(Object.keys(r1.items[0]).sort().join(',')).toBe('body,id,title');
|
||||
expect(r1.items.length).toBe(2);
|
||||
expect(r1.items[0].title).toBe('note1');
|
||||
expect(r1.items[0].body).toBe('noteBody1');
|
||||
expect(r1.items[1].title).toBe('note2');
|
||||
expect(r1.items[1].body).toBe('noteBody2');
|
||||
|
||||
const r2 = await api.route(RequestMethod.GET, 'notes', { ...baseQuery, fields: ['id'], page: 2 });
|
||||
|
||||
expect(Object.keys(r2.items[0]).sort().join(',')).toBe('id');
|
||||
expect(r2.items.length).toBe(1);
|
||||
expect(!!r2.items[0].id).toBe(true);
|
||||
}));
|
||||
|
||||
it('should paginate folder notes', asyncTest(async () => {
|
||||
const folder = await Folder.save({});
|
||||
const note1 = await Note.save({ parent_id: folder.id });
|
||||
@@ -606,7 +635,8 @@ describe('services_rest_Api', function() {
|
||||
expect(r1.items[1].id).toBe(note2.id);
|
||||
|
||||
const r2 = await api.route(RequestMethod.GET, `folders/${folder.id}/notes`, {
|
||||
cursor: r1.cursor,
|
||||
limit: 2,
|
||||
page: 2,
|
||||
});
|
||||
|
||||
expect(r2.items.length).toBe(1);
|
||||
@@ -666,6 +696,44 @@ describe('services_rest_Api', function() {
|
||||
const r = await api.route(RequestMethod.GET, `resources/${resource.id}/notes`);
|
||||
|
||||
expect(r.items.length).toBe(1);
|
||||
expect(r.items[0]).toBe(note.id);
|
||||
expect(r.items[0].id).toBe(note.id);
|
||||
}));
|
||||
|
||||
it('should return the resources associated with a note', asyncTest(async () => {
|
||||
const note = await Note.save({});
|
||||
await shim.attachFileToNote(note, `${__dirname}/../tests/support/photo.jpg`);
|
||||
const resource = (await Resource.all())[0];
|
||||
|
||||
const r = await api.route(RequestMethod.GET, `notes/${note.id}/resources`);
|
||||
|
||||
expect(r.items.length).toBe(1);
|
||||
expect(r.items[0].id).toBe(resource.id);
|
||||
}));
|
||||
|
||||
it('should return search results', asyncTest(async () => {
|
||||
SearchEngine.instance().setDb(db());
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
await Note.save({ title: 'a' });
|
||||
}
|
||||
|
||||
await SearchEngine.instance().syncTables();
|
||||
|
||||
// Mostly testing pagination below
|
||||
|
||||
const r1 = await api.route(RequestMethod.GET, 'search', { query: 'a', limit: 4 });
|
||||
expect(r1.items.length).toBe(4);
|
||||
expect(r1.has_more).toBe(true);
|
||||
|
||||
const r2 = await api.route(RequestMethod.GET, 'search', { query: 'a', limit: 4, page: 2 });
|
||||
expect(r2.items.length).toBe(4);
|
||||
expect(r2.has_more).toBe(true);
|
||||
|
||||
const r3 = await api.route(RequestMethod.GET, 'search', { query: 'a', limit: 4, page: 3 });
|
||||
expect(r3.items.length).toBe(2);
|
||||
expect(!!r3.has_more).toBe(false);
|
||||
|
||||
await SearchEngine.instance().destroy();
|
||||
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"spec_dir": "tests",
|
||||
"spec_files": [
|
||||
"*.js",
|
||||
"services/plugins/*.js",
|
||||
"services/plugins/api/*.js",
|
||||
"!test-utils.js"
|
||||
],
|
||||
"stopSpecOnExpectationFailure": false,
|
||||
"random": true
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import Plugin from '../Plugin';
|
||||
import Joplin from './Joplin';
|
||||
import Logger from 'lib/Logger';
|
||||
import Logger from '../../../Logger';
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
@@ -7,9 +7,21 @@ import JoplinCommands from './JoplinCommands';
|
||||
import JoplinViews from './JoplinViews';
|
||||
import JoplinInterop from './JoplinInterop';
|
||||
import JoplinSettings from './JoplinSettings';
|
||||
import Logger from 'lib/Logger';
|
||||
import Logger from '../../../Logger';
|
||||
/**
|
||||
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
|
||||
*
|
||||
* **This is a beta API**
|
||||
*
|
||||
* Please note that the plugin API is relatively new and should be considered Beta state. Besides possible bugs, what it means is that there might be necessary breaking changes from one version to the next. Whenever such change is needed, best effort will be done to:
|
||||
*
|
||||
* - Maintain backward compatibility;
|
||||
* - When possible, deprecate features instead of removing them;
|
||||
* - Document breaking changes in the changelog;
|
||||
*
|
||||
* So if you are developing a plugin, please keep an eye on the changelog as everything will be in there with information about how to update your code. There won't be any major API rewrite or architecture changes, but possibly small tweaks like function signature change, type change, etc.
|
||||
*
|
||||
* Eventually, the plugin API will be versioned to make this process smoother.
|
||||
*/
|
||||
export default class Joplin {
|
||||
private data_;
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
import { Command } from './types';
|
||||
/**
|
||||
* This class allows executing or registering new Joplin commands. Commands can be executed or associated with
|
||||
* {@link JoplinViewsToolbarButtons | toolbar buttons} or {@link JoplinViewsMenuItems | menu items}.
|
||||
* This class allows executing or registering new Joplin commands. Commands
|
||||
* can be executed or associated with
|
||||
* {@link JoplinViewsToolbarButtons | toolbar buttons} or
|
||||
* {@link JoplinViewsMenuItems | menu items}.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/register_command)
|
||||
*
|
||||
* ## Executing Joplin's internal commands
|
||||
*
|
||||
* It is also possible to execute internal Joplin's commands which, as of now, are not well documented.
|
||||
* You can find the list directly on GitHub though at the following locations:
|
||||
* It is also possible to execute internal Joplin's commands which, as of
|
||||
* now, are not well documented. You can find the list directly on GitHub
|
||||
* though at the following locations:
|
||||
*
|
||||
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/MainScreen/commands
|
||||
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/commands
|
||||
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.ts
|
||||
* * [Main screen commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/MainScreen/commands)
|
||||
* * [Global commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/commands)
|
||||
* * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.ts)
|
||||
*
|
||||
* To view what arguments are supported, you can open any of these files and look at the `execute()` command.
|
||||
* To view what arguments are supported, you can open any of these files
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given command.
|
||||
* The `props` are the arguments passed to the command, and they vary based on the command
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
* The command can take any number of arguments, and the supported
|
||||
* arguments will vary based on the command. For custom commands, this
|
||||
* is the `args` passed to the `execute()` function. For built-in
|
||||
* commands, you can find the supported arguments by checking the links
|
||||
* above.
|
||||
*
|
||||
* ```typescript
|
||||
* // Create a new note in the current notebook:
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Path } from './types';
|
||||
*
|
||||
* This is also what you would use to search notes, via the `search` endpoint.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/simple)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/simple)
|
||||
*
|
||||
* In general you would use the methods in this class as if you were using a REST API. There are four methods that map to GET, POST, PUT and DELETE calls.
|
||||
* And each method takes these parameters:
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ExportModule, ImportModule } from './types';
|
||||
/**
|
||||
* Provides a way to create modules to import external data into Joplin or to export notes into any arbitrary format.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/json_export)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/json_export)
|
||||
*
|
||||
* To implement an import or export module, you would simply define an object with various event handlers that are called
|
||||
* by the application during the import/export process.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Plugin from '../Plugin';
|
||||
import Logger from 'lib/Logger';
|
||||
import Logger from '../../../Logger';
|
||||
import { ContentScriptType, Script } from './types';
|
||||
/**
|
||||
* This class provides access to plugin-related features.
|
||||
@@ -28,7 +28,7 @@ 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/CliClient/tests/support/plugins/content_script)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/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.
|
||||
|
||||
@@ -7,7 +7,7 @@ import { SettingItem, SettingSection } from './types';
|
||||
*
|
||||
* Note: Currently this API does **not** provide access to Joplin's built-in settings. This is by design as plugins that modify user settings could give unexpected results
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/settings)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/settings)
|
||||
*/
|
||||
export default class JoplinSettings {
|
||||
private plugin_;
|
||||
@@ -37,7 +37,7 @@ export default class JoplinSettings {
|
||||
*
|
||||
* The list of available settings is not documented yet, but can be found by looking at the source code:
|
||||
*
|
||||
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/ReactNativeClient/lib/models/Setting.ts#L142
|
||||
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142
|
||||
*/
|
||||
globalValue(key: string): Promise<any>;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ButtonSpec, ViewHandle, ButtonId } from './types';
|
||||
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 and provide the button ID that was
|
||||
* clicked on. 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.
|
||||
* 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.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/dialog)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/dialog)
|
||||
*/
|
||||
export default class JoplinViewsDialogs {
|
||||
private store;
|
||||
@@ -16,7 +17,7 @@ export default class JoplinViewsDialogs {
|
||||
/**
|
||||
* Creates a new dialog
|
||||
*/
|
||||
create(): Promise<ViewHandle>;
|
||||
create(id: string): Promise<ViewHandle>;
|
||||
/**
|
||||
* Displays a message box with OK/Cancel buttons. Returns the button index that was clicked - "0" for OK and "1" for "Cancel"
|
||||
*/
|
||||
@@ -32,5 +33,5 @@ export default class JoplinViewsDialogs {
|
||||
/**
|
||||
* Opens the dialog
|
||||
*/
|
||||
open(handle: ViewHandle): Promise<ButtonId>;
|
||||
open(handle: ViewHandle): Promise<DialogResult>;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import Plugin from '../Plugin';
|
||||
/**
|
||||
* Allows creating and managing menu items.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/register_command)
|
||||
*/
|
||||
export default class JoplinViewsMenuItems {
|
||||
private store;
|
||||
@@ -12,5 +12,5 @@ export default class JoplinViewsMenuItems {
|
||||
/**
|
||||
* Creates a new menu item and associate it with the given command. You can specify under which menu the item should appear using the `location` parameter.
|
||||
*/
|
||||
create(commandName: string, location?: MenuItemLocation, options?: CreateMenuItemOptions): Promise<void>;
|
||||
create(id: string, commandName: string, location?: MenuItemLocation, options?: CreateMenuItemOptions): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import Plugin from '../Plugin';
|
||||
/**
|
||||
* Allows creating menus.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/menu)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/menu)
|
||||
*/
|
||||
export default class JoplinViewsMenus {
|
||||
private store;
|
||||
@@ -14,5 +14,5 @@ export default class JoplinViewsMenus {
|
||||
* Creates a new menu from the provided menu items and place it at the given location. As of now, it is only possible to place the
|
||||
* menu as a sub-menu of the application build-in menus.
|
||||
*/
|
||||
create(label: string, menuItems: MenuItem[], location?: MenuItemLocation): Promise<void>;
|
||||
create(id: string, label: string, menuItems: MenuItem[], location?: MenuItemLocation): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import Plugin from '../Plugin';
|
||||
import { ViewHandle } from './types';
|
||||
/**
|
||||
* Allows creating and managing view panels. View panels currently are displayed at the right of the sidebar and allows displaying any HTML content (within a webview) and update it in real-time. For example
|
||||
* it could be used to display a table of content for the active note, or display various metadata or graph.
|
||||
* Allows creating and managing view panels. View panels currently are
|
||||
* displayed at the right of the sidebar and allows displaying any HTML
|
||||
* content (within a webview) and update it in real-time. For example it
|
||||
* could be used to display a table of content for the active note, or
|
||||
* display various metadata or graph.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/toc)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/toc)
|
||||
*/
|
||||
export default class JoplinViewsPanels {
|
||||
private store;
|
||||
@@ -14,7 +17,7 @@ export default class JoplinViewsPanels {
|
||||
/**
|
||||
* Creates a new panel
|
||||
*/
|
||||
create(): Promise<ViewHandle>;
|
||||
create(id: string): Promise<ViewHandle>;
|
||||
/**
|
||||
* Sets the panel webview HTML
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@ import Plugin from '../Plugin';
|
||||
/**
|
||||
* Allows creating and managing toolbar buttons.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/register_command)
|
||||
*/
|
||||
export default class JoplinViewsToolbarButtons {
|
||||
private store;
|
||||
@@ -12,5 +12,5 @@ export default class JoplinViewsToolbarButtons {
|
||||
/**
|
||||
* Creates a new toolbar button and associate it with the given command.
|
||||
*/
|
||||
create(commandName: string, location: ToolbarButtonLocation): Promise<void>;
|
||||
create(id: string, commandName: string, location: ToolbarButtonLocation): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* The workspace service provides access to all the parts of Joplin that are being worked on - i.e. the currently selected notes or notebooks as well
|
||||
* as various related events, such as when a new note is selected, or when the note content changes.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
|
||||
*/
|
||||
export default class JoplinWorkspace {
|
||||
private store;
|
||||
|
||||
@@ -6,7 +6,7 @@ export interface Command {
|
||||
/**
|
||||
* Name of command - must be globally unique
|
||||
*/
|
||||
name: string
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Label to be displayed on menu items or keyboard shortcut editor for example.
|
||||
@@ -14,17 +14,17 @@ export interface Command {
|
||||
* In that case the command will not appear in the shortcut editor or command panel, and logically
|
||||
* should not be used as a menu item.
|
||||
*/
|
||||
label?: string
|
||||
label?: string;
|
||||
|
||||
/**
|
||||
* Icon to be used on toolbar buttons for example
|
||||
*/
|
||||
iconName?: string,
|
||||
iconName?: string;
|
||||
|
||||
/**
|
||||
* Code to be ran when the command is executed. It may return a result.
|
||||
*/
|
||||
execute(...args:any[]):Promise<any | void>
|
||||
execute(...args: any[]): Promise<any | void>;
|
||||
|
||||
/**
|
||||
* Defines whether the command should be enabled or disabled, which in turns affects
|
||||
@@ -40,13 +40,11 @@ export interface Command {
|
||||
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
|
||||
* And | && | "oneNoteSelected && !inConflictFolder"
|
||||
*
|
||||
* Currently the supported context variables aren't documented, but you can find the list there:
|
||||
*
|
||||
* https://github.com/laurent22/joplin/blob/dev/ReactNativeClient/lib/services/commands/stateToWhenClauseContext.ts
|
||||
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts).
|
||||
*
|
||||
* Note: Commands are enabled by default unless you use this property.
|
||||
*/
|
||||
enabledCondition?: string
|
||||
enabledCondition?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
@@ -64,7 +62,7 @@ export enum ImportModuleOutputFormat {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to implement a module to export data from Joplin. [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/json_export) for an example.
|
||||
* Used to implement a module to export data from Joplin. [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/json_export) for an example.
|
||||
*
|
||||
* In general, all the event handlers you'll need to implement take a `context` object as a first argument. This object will contain the export or import path as well as various optional properties, such as which notes or notebooks need to be exported.
|
||||
*
|
||||
@@ -74,113 +72,113 @@ export interface ExportModule {
|
||||
/**
|
||||
* The format to be exported, eg "enex", "jex", "json", etc.
|
||||
*/
|
||||
format: string,
|
||||
format: string;
|
||||
|
||||
/**
|
||||
* The description that will appear in the UI, for example in the menu item.
|
||||
*/
|
||||
description: string,
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* Whether the module will export a single file or multiple files in a directory. It affects the open dialog that will be presented to the user when using your exporter.
|
||||
*/
|
||||
target: FileSystemItem,
|
||||
target: FileSystemItem;
|
||||
|
||||
/**
|
||||
* Only applies to single file exporters or importers
|
||||
* It tells whether the format can package multiple notes into one file.
|
||||
* For example JEX or ENEX can, but HTML cannot.
|
||||
*/
|
||||
isNoteArchive: boolean,
|
||||
isNoteArchive: boolean;
|
||||
|
||||
/**
|
||||
* The extensions of the files exported by your module. For example, it is `["htm", "html"]` for the HTML module, and just `["jex"]` for the JEX module.
|
||||
*/
|
||||
fileExtensions?: string[],
|
||||
fileExtensions?: string[];
|
||||
|
||||
/**
|
||||
* Called when the export process starts.
|
||||
*/
|
||||
onInit(context:ExportContext): Promise<void>;
|
||||
onInit(context: ExportContext): Promise<void>;
|
||||
|
||||
/**
|
||||
* Called when an item needs to be processed. An "item" can be any Joplin object, such as a note, a folder, a notebook, etc.
|
||||
*/
|
||||
onProcessItem(context:ExportContext, itemType:number, item:any):Promise<void>;
|
||||
onProcessItem(context: ExportContext, itemType: number, item: any): Promise<void>;
|
||||
|
||||
/**
|
||||
* Called when a resource file needs to be exported.
|
||||
*/
|
||||
onProcessResource(context:ExportContext, resource:any, filePath:string):Promise<void>;
|
||||
onProcessResource(context: ExportContext, resource: any, filePath: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Called when the export process is done.
|
||||
*/
|
||||
onClose(context:ExportContext):Promise<void>;
|
||||
onClose(context: ExportContext): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ImportModule {
|
||||
/**
|
||||
* The format to be exported, eg "enex", "jex", "json", etc.
|
||||
*/
|
||||
format: string,
|
||||
format: string;
|
||||
|
||||
/**
|
||||
* The description that will appear in the UI, for example in the menu item.
|
||||
*/
|
||||
description: string,
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* Only applies to single file exporters or importers
|
||||
* It tells whether the format can package multiple notes into one file.
|
||||
* For example JEX or ENEX can, but HTML cannot.
|
||||
*/
|
||||
isNoteArchive: boolean,
|
||||
isNoteArchive: boolean;
|
||||
|
||||
/**
|
||||
* The type of sources that are supported by the module. Tells whether the module can import files or directories or both.
|
||||
*/
|
||||
sources: FileSystemItem[],
|
||||
sources: FileSystemItem[];
|
||||
|
||||
/**
|
||||
* Tells the file extensions of the exported files.
|
||||
*/
|
||||
fileExtensions?: string[],
|
||||
fileExtensions?: string[];
|
||||
|
||||
/**
|
||||
* Tells the type of notes that will be generated, either HTML or Markdown (default).
|
||||
*/
|
||||
outputFormat?: ImportModuleOutputFormat,
|
||||
outputFormat?: ImportModuleOutputFormat;
|
||||
|
||||
/**
|
||||
* Called when the import process starts. There is only one event handler within which you should import the complete data.
|
||||
*/
|
||||
onExec(context:ImportContext): Promise<void>;
|
||||
onExec(context: ImportContext): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExportOptions {
|
||||
format?: string,
|
||||
path?:string,
|
||||
sourceFolderIds?: string[],
|
||||
sourceNoteIds?: string[],
|
||||
modulePath?:string,
|
||||
target?:FileSystemItem,
|
||||
format?: string;
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
export interface ExportContext {
|
||||
destPath: string,
|
||||
options: ExportOptions,
|
||||
destPath: string;
|
||||
options: ExportOptions;
|
||||
|
||||
/**
|
||||
* You can attach your own custom data using this propery - it will then be passed to each event handler, allowing you to keep state from one event to the next.
|
||||
*/
|
||||
userData?: any,
|
||||
userData?: any;
|
||||
}
|
||||
|
||||
export interface ImportContext {
|
||||
sourcePath: string,
|
||||
options: any,
|
||||
warnings: string[],
|
||||
sourcePath: string;
|
||||
options: any;
|
||||
warnings: string[];
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
@@ -188,7 +186,7 @@ export interface ImportContext {
|
||||
// =================================================================
|
||||
|
||||
export interface Script {
|
||||
onStart?(event:any):Promise<void>,
|
||||
onStart?(event: any): Promise<void>;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
@@ -196,7 +194,7 @@ export interface Script {
|
||||
// =================================================================
|
||||
|
||||
export interface CreateMenuItemOptions {
|
||||
accelerator: string,
|
||||
accelerator: string;
|
||||
}
|
||||
|
||||
export enum MenuItemLocation {
|
||||
@@ -206,7 +204,12 @@ export enum MenuItemLocation {
|
||||
Note = 'note',
|
||||
Tools = 'tools',
|
||||
Help = 'help',
|
||||
/*
|
||||
* Deprecated - do not use - same as NoteListContext
|
||||
*/
|
||||
Context = 'context',
|
||||
NoteListContextMenu = 'noteListContextMenu',
|
||||
EditorContextMenu = 'editorContextMenu',
|
||||
}
|
||||
|
||||
export interface MenuItem {
|
||||
@@ -214,22 +217,22 @@ export interface MenuItem {
|
||||
* Command that should be associated with the menu item. All menu item should
|
||||
* have a command associated with them unless they are a sub-menu.
|
||||
*/
|
||||
commandName?: string,
|
||||
commandName?: string;
|
||||
|
||||
/**
|
||||
* Accelerator associated with the menu item
|
||||
*/
|
||||
accelerator?: string,
|
||||
accelerator?: string;
|
||||
|
||||
/**
|
||||
* Menu items that should appear below this menu item. Allows creating a menu tree.
|
||||
*/
|
||||
submenu?: MenuItem[],
|
||||
submenu?: MenuItem[];
|
||||
|
||||
/**
|
||||
* Menu item label. If not specified, the command label will be used instead.
|
||||
*/
|
||||
label?: string,
|
||||
label?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
@@ -237,9 +240,9 @@ export interface MenuItem {
|
||||
// =================================================================
|
||||
|
||||
export interface ButtonSpec {
|
||||
id: ButtonId,
|
||||
title?: string,
|
||||
onClick?():void,
|
||||
id: ButtonId;
|
||||
title?: string;
|
||||
onClick?(): void;
|
||||
}
|
||||
|
||||
export type ButtonId = string;
|
||||
@@ -263,6 +266,11 @@ export interface EditorCommand {
|
||||
value?: any;
|
||||
}
|
||||
|
||||
export interface DialogResult {
|
||||
id: ButtonId;
|
||||
formData?: any;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Settings types
|
||||
// =================================================================
|
||||
@@ -279,28 +287,28 @@ export enum SettingItemType {
|
||||
// Redefine a simplified interface to mask internal details
|
||||
// and to remove function calls as they would have to be async.
|
||||
export interface SettingItem {
|
||||
value: any,
|
||||
type: SettingItemType,
|
||||
public: boolean,
|
||||
label:string,
|
||||
value: any;
|
||||
type: SettingItemType;
|
||||
public: boolean;
|
||||
label: string;
|
||||
|
||||
description?:string,
|
||||
isEnum?: boolean,
|
||||
section?: string,
|
||||
options?:any,
|
||||
appTypes?:string[],
|
||||
secure?: boolean,
|
||||
advanced?: boolean,
|
||||
minimum?: number,
|
||||
maximum?: number,
|
||||
step?: number,
|
||||
description?: string;
|
||||
isEnum?: boolean;
|
||||
section?: string;
|
||||
options?: any;
|
||||
appTypes?: string[];
|
||||
secure?: boolean;
|
||||
advanced?: boolean;
|
||||
minimum?: number;
|
||||
maximum?: number;
|
||||
step?: number;
|
||||
}
|
||||
|
||||
export interface SettingSection {
|
||||
label: string,
|
||||
iconName?: string,
|
||||
description?: string,
|
||||
name?: string,
|
||||
label: string;
|
||||
iconName?: string;
|
||||
description?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
@@ -322,36 +330,30 @@ export type Path = string[];
|
||||
|
||||
export enum ContentScriptType {
|
||||
/**
|
||||
* Registers a new Markdown-It plugin, which should follow this template:
|
||||
* Registers a new Markdown-It plugin, which should follow the template below.
|
||||
*
|
||||
* ```javascript
|
||||
* // The module should export an object as below:
|
||||
*
|
||||
* module.exports = {
|
||||
*
|
||||
* // The "context" variable 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.
|
||||
* default: function(context) {
|
||||
* return {
|
||||
*
|
||||
* // This is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information
|
||||
* // The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/ReactNativeClient/lib/joplin-renderer/MdToHtml.ts), which
|
||||
* // contains a number of options, mostly useful for Joplin's internal code.
|
||||
* plugin: function(markdownIt, options) {
|
||||
* // ...
|
||||
* },
|
||||
*
|
||||
* // You may also specify additional assets such as JS or CSS that should be loaded in the rendered HTML document.
|
||||
* // Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to
|
||||
* // see how the data should be structured.
|
||||
* assets: {},
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific feature, you
|
||||
* would simply create a file such as this:
|
||||
* - 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 **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code.
|
||||
*
|
||||
* - Using the **optional** `assets` key you may specify assets such as JS or CSS 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.
|
||||
*
|
||||
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this:
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Plugin from '../Plugin';
|
||||
import Joplin from './Joplin';
|
||||
import Logger from 'lib/Logger';
|
||||
import Logger from '../../../Logger';
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
@@ -7,9 +7,21 @@ import JoplinCommands from './JoplinCommands';
|
||||
import JoplinViews from './JoplinViews';
|
||||
import JoplinInterop from './JoplinInterop';
|
||||
import JoplinSettings from './JoplinSettings';
|
||||
import Logger from 'lib/Logger';
|
||||
import Logger from '../../../Logger';
|
||||
/**
|
||||
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
|
||||
*
|
||||
* **This is a beta API**
|
||||
*
|
||||
* Please note that the plugin API is relatively new and should be considered Beta state. Besides possible bugs, what it means is that there might be necessary breaking changes from one version to the next. Whenever such change is needed, best effort will be done to:
|
||||
*
|
||||
* - Maintain backward compatibility;
|
||||
* - When possible, deprecate features instead of removing them;
|
||||
* - Document breaking changes in the changelog;
|
||||
*
|
||||
* So if you are developing a plugin, please keep an eye on the changelog as everything will be in there with information about how to update your code. There won't be any major API rewrite or architecture changes, but possibly small tweaks like function signature change, type change, etc.
|
||||
*
|
||||
* Eventually, the plugin API will be versioned to make this process smoother.
|
||||
*/
|
||||
export default class Joplin {
|
||||
private data_;
|
||||
|
||||
@@ -1,25 +1,35 @@
|
||||
import { Command } from './types';
|
||||
/**
|
||||
* This class allows executing or registering new Joplin commands. Commands can be executed or associated with
|
||||
* {@link JoplinViewsToolbarButtons | toolbar buttons} or {@link JoplinViewsMenuItems | menu items}.
|
||||
* This class allows executing or registering new Joplin commands. Commands
|
||||
* can be executed or associated with
|
||||
* {@link JoplinViewsToolbarButtons | toolbar buttons} or
|
||||
* {@link JoplinViewsMenuItems | menu items}.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/register_command)
|
||||
*
|
||||
* ## Executing Joplin's internal commands
|
||||
*
|
||||
* It is also possible to execute internal Joplin's commands which, as of now, are not well documented.
|
||||
* You can find the list directly on GitHub though at the following locations:
|
||||
* It is also possible to execute internal Joplin's commands which, as of
|
||||
* now, are not well documented. You can find the list directly on GitHub
|
||||
* though at the following locations:
|
||||
*
|
||||
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/MainScreen/commands
|
||||
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/commands
|
||||
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.ts
|
||||
* * [Main screen commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/MainScreen/commands)
|
||||
* * [Global commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/commands)
|
||||
* * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.ts)
|
||||
*
|
||||
* To view what arguments are supported, you can open any of these files and look at the `execute()` command.
|
||||
* To view what arguments are supported, you can open any of these files
|
||||
* and look at the `execute()` command.
|
||||
*/
|
||||
export default class JoplinCommands {
|
||||
/**
|
||||
* <span class="platform-desktop">desktop</span> Executes the given command.
|
||||
* The `props` are the arguments passed to the command, and they vary based on the command
|
||||
* <span class="platform-desktop">desktop</span> Executes the given
|
||||
* command.
|
||||
*
|
||||
* The command can take any number of arguments, and the supported
|
||||
* arguments will vary based on the command. For custom commands, this
|
||||
* is the `args` passed to the `execute()` function. For built-in
|
||||
* commands, you can find the supported arguments by checking the links
|
||||
* above.
|
||||
*
|
||||
* ```typescript
|
||||
* // Create a new note in the current notebook:
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Path } from './types';
|
||||
*
|
||||
* This is also what you would use to search notes, via the `search` endpoint.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/simple)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/simple)
|
||||
*
|
||||
* In general you would use the methods in this class as if you were using a REST API. There are four methods that map to GET, POST, PUT and DELETE calls.
|
||||
* And each method takes these parameters:
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ExportModule, ImportModule } from './types';
|
||||
/**
|
||||
* Provides a way to create modules to import external data into Joplin or to export notes into any arbitrary format.
|
||||
*
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/json_export)
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/json_export)
|
||||
*
|
||||
* To implement an import or export module, you would simply define an object with various event handlers that are called
|
||||
* by the application during the import/export process.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user