From f4f96cfe89a148004edc3e9ede875e0f74bb859a Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Thu, 5 Jan 2023 10:41:17 +0000 Subject: [PATCH] Update plugin types --- .../codemirror_content_script/api/Joplin.d.ts | 11 ++--- .../api/JoplinCommands.d.ts | 10 ++--- .../api/JoplinData.d.ts | 3 ++ .../api/JoplinFilters.d.ts | 4 +- .../api/JoplinInterop.d.ts | 4 +- .../api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../api/JoplinViewsPanels.d.ts | 17 ++++++++ .../api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../codemirror_content_script/api/types.ts | 42 +++++++++++++++++++ .../codemirror_content_script/package.json | 17 ++++---- .../webpack.config.js | 14 ++++++- .../plugins/content_script/api/Joplin.d.ts | 11 ++--- .../content_script/api/JoplinCommands.d.ts | 10 ++--- .../content_script/api/JoplinData.d.ts | 3 ++ .../content_script/api/JoplinFilters.d.ts | 4 +- .../content_script/api/JoplinInterop.d.ts | 4 +- .../content_script/api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../content_script/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../content_script/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/content_script/api/types.ts | 42 +++++++++++++++++++ .../plugins/content_script/package.json | 17 ++++---- .../plugins/content_script/webpack.config.js | 14 ++++++- .../support/plugins/dialog/api/Joplin.d.ts | 11 ++--- .../plugins/dialog/api/JoplinCommands.d.ts | 10 ++--- .../plugins/dialog/api/JoplinData.d.ts | 3 ++ .../plugins/dialog/api/JoplinFilters.d.ts | 4 +- .../plugins/dialog/api/JoplinInterop.d.ts | 4 +- .../plugins/dialog/api/JoplinSettings.d.ts | 2 +- .../dialog/api/JoplinViewsDialogs.d.ts | 3 +- .../plugins/dialog/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../plugins/dialog/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../tests/support/plugins/dialog/api/types.ts | 42 +++++++++++++++++++ .../tests/support/plugins/dialog/package.json | 17 ++++---- .../support/plugins/dialog/webpack.config.js | 14 ++++++- .../editor_context_menu/api/Joplin.d.ts | 11 ++--- .../api/JoplinCommands.d.ts | 10 ++--- .../editor_context_menu/api/JoplinData.d.ts | 3 ++ .../api/JoplinFilters.d.ts | 4 +- .../api/JoplinInterop.d.ts | 4 +- .../api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../api/JoplinViewsPanels.d.ts | 17 ++++++++ .../api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/editor_context_menu/api/types.ts | 42 +++++++++++++++++++ .../plugins/editor_context_menu/package.json | 17 ++++---- .../editor_context_menu/webpack.config.js | 14 ++++++- .../support/plugins/events/api/Joplin.d.ts | 11 ++--- .../plugins/events/api/JoplinCommands.d.ts | 10 ++--- .../plugins/events/api/JoplinData.d.ts | 3 ++ .../plugins/events/api/JoplinFilters.d.ts | 4 +- .../plugins/events/api/JoplinInterop.d.ts | 4 +- .../plugins/events/api/JoplinSettings.d.ts | 2 +- .../events/api/JoplinViewsDialogs.d.ts | 3 +- .../plugins/events/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../plugins/events/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../tests/support/plugins/events/api/types.ts | 42 +++++++++++++++++++ .../tests/support/plugins/events/package.json | 17 ++++---- .../support/plugins/events/webpack.config.js | 14 ++++++- .../plugins/external_assets/api/Joplin.d.ts | 11 ++--- .../external_assets/api/JoplinCommands.d.ts | 10 ++--- .../external_assets/api/JoplinData.d.ts | 3 ++ .../external_assets/api/JoplinFilters.d.ts | 4 +- .../external_assets/api/JoplinInterop.d.ts | 4 +- .../external_assets/api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../api/JoplinViewsPanels.d.ts | 17 ++++++++ .../external_assets/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/external_assets/api/types.ts | 42 +++++++++++++++++++ .../plugins/external_assets/package.json | 17 ++++---- .../plugins/external_assets/webpack.config.js | 14 ++++++- .../support/plugins/jpl_test/api/Joplin.d.ts | 11 ++--- .../plugins/jpl_test/api/JoplinCommands.d.ts | 10 ++--- .../plugins/jpl_test/api/JoplinData.d.ts | 3 ++ .../plugins/jpl_test/api/JoplinFilters.d.ts | 4 +- .../plugins/jpl_test/api/JoplinInterop.d.ts | 4 +- .../plugins/jpl_test/api/JoplinSettings.d.ts | 2 +- .../jpl_test/api/JoplinViewsDialogs.d.ts | 3 +- .../jpl_test/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../plugins/jpl_test/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../support/plugins/jpl_test/api/types.ts | 42 +++++++++++++++++++ .../support/plugins/jpl_test/package.json | 17 ++++---- .../plugins/jpl_test/webpack.config.js | 14 ++++++- .../plugins/json_export/api/Joplin.d.ts | 11 ++--- .../json_export/api/JoplinCommands.d.ts | 10 ++--- .../plugins/json_export/api/JoplinData.d.ts | 3 ++ .../json_export/api/JoplinFilters.d.ts | 4 +- .../json_export/api/JoplinInterop.d.ts | 4 +- .../json_export/api/JoplinSettings.d.ts | 2 +- .../json_export/api/JoplinViewsDialogs.d.ts | 3 +- .../json_export/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../json_export/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../support/plugins/json_export/api/types.ts | 42 +++++++++++++++++++ .../support/plugins/json_export/package.json | 17 ++++---- .../plugins/json_export/webpack.config.js | 14 ++++++- .../support/plugins/menu/api/Joplin.d.ts | 11 ++--- .../plugins/menu/api/JoplinCommands.d.ts | 10 ++--- .../support/plugins/menu/api/JoplinData.d.ts | 3 ++ .../plugins/menu/api/JoplinFilters.d.ts | 4 +- .../plugins/menu/api/JoplinInterop.d.ts | 4 +- .../plugins/menu/api/JoplinSettings.d.ts | 2 +- .../plugins/menu/api/JoplinViewsDialogs.d.ts | 3 +- .../plugins/menu/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../plugins/menu/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../tests/support/plugins/menu/api/types.ts | 42 +++++++++++++++++++ .../tests/support/plugins/menu/package.json | 17 ++++---- .../support/plugins/menu/webpack.config.js | 14 ++++++- .../plugins/multi_selection/api/Joplin.d.ts | 11 ++--- .../multi_selection/api/JoplinCommands.d.ts | 10 ++--- .../multi_selection/api/JoplinData.d.ts | 3 ++ .../multi_selection/api/JoplinFilters.d.ts | 4 +- .../multi_selection/api/JoplinInterop.d.ts | 4 +- .../multi_selection/api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../api/JoplinViewsPanels.d.ts | 17 ++++++++ .../multi_selection/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/multi_selection/api/types.ts | 42 +++++++++++++++++++ .../plugins/multi_selection/package.json | 17 ++++---- .../plugins/multi_selection/webpack.config.js | 14 ++++++- .../plugins/nativeModule/api/Joplin.d.ts | 11 ++--- .../nativeModule/api/JoplinCommands.d.ts | 10 ++--- .../plugins/nativeModule/api/JoplinData.d.ts | 3 ++ .../nativeModule/api/JoplinFilters.d.ts | 4 +- .../nativeModule/api/JoplinInterop.d.ts | 4 +- .../nativeModule/api/JoplinSettings.d.ts | 2 +- .../nativeModule/api/JoplinViewsDialogs.d.ts | 3 +- .../nativeModule/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../nativeModule/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../support/plugins/nativeModule/api/types.ts | 42 +++++++++++++++++++ .../support/plugins/nativeModule/package.json | 17 ++++---- .../plugins/nativeModule/webpack.config.js | 14 ++++++- .../plugins/post_messages/api/Joplin.d.ts | 11 ++--- .../post_messages/api/JoplinCommands.d.ts | 10 ++--- .../plugins/post_messages/api/JoplinData.d.ts | 3 ++ .../post_messages/api/JoplinFilters.d.ts | 4 +- .../post_messages/api/JoplinInterop.d.ts | 4 +- .../post_messages/api/JoplinSettings.d.ts | 2 +- .../post_messages/api/JoplinViewsDialogs.d.ts | 3 +- .../post_messages/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../post_messages/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/post_messages/api/types.ts | 42 +++++++++++++++++++ .../plugins/post_messages/package.json | 17 ++++---- .../plugins/post_messages/webpack.config.js | 14 ++++++- .../plugins/register_command/api/Joplin.d.ts | 11 ++--- .../register_command/api/JoplinCommands.d.ts | 10 ++--- .../register_command/api/JoplinData.d.ts | 3 ++ .../register_command/api/JoplinFilters.d.ts | 4 +- .../register_command/api/JoplinInterop.d.ts | 4 +- .../register_command/api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../api/JoplinViewsPanels.d.ts | 17 ++++++++ .../register_command/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/register_command/api/types.ts | 42 +++++++++++++++++++ .../plugins/register_command/package.json | 17 ++++---- .../register_command/webpack.config.js | 14 ++++++- .../plugins/selected_text/api/Joplin.d.ts | 11 ++--- .../selected_text/api/JoplinCommands.d.ts | 10 ++--- .../plugins/selected_text/api/JoplinData.d.ts | 3 ++ .../selected_text/api/JoplinFilters.d.ts | 4 +- .../selected_text/api/JoplinInterop.d.ts | 4 +- .../selected_text/api/JoplinSettings.d.ts | 2 +- .../selected_text/api/JoplinViewsDialogs.d.ts | 3 +- .../selected_text/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../selected_text/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/selected_text/api/types.ts | 42 +++++++++++++++++++ .../plugins/selected_text/package.json | 17 ++++---- .../plugins/selected_text/webpack.config.js | 14 ++++++- .../support/plugins/settings/api/Joplin.d.ts | 11 ++--- .../plugins/settings/api/JoplinCommands.d.ts | 10 ++--- .../plugins/settings/api/JoplinData.d.ts | 3 ++ .../plugins/settings/api/JoplinFilters.d.ts | 4 +- .../plugins/settings/api/JoplinInterop.d.ts | 4 +- .../plugins/settings/api/JoplinSettings.d.ts | 2 +- .../settings/api/JoplinViewsDialogs.d.ts | 3 +- .../settings/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../plugins/settings/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../support/plugins/settings/api/types.ts | 35 ++++++++++++++++ .../support/plugins/settings/package.json | 17 ++++---- .../plugins/settings/webpack.config.js | 14 ++++++- .../tests/support/plugins/toc/api/Joplin.d.ts | 11 ++--- .../plugins/toc/api/JoplinCommands.d.ts | 10 ++--- .../support/plugins/toc/api/JoplinData.d.ts | 3 ++ .../plugins/toc/api/JoplinFilters.d.ts | 4 +- .../plugins/toc/api/JoplinInterop.d.ts | 4 +- .../plugins/toc/api/JoplinSettings.d.ts | 2 +- .../plugins/toc/api/JoplinViewsDialogs.d.ts | 3 +- .../plugins/toc/api/JoplinViewsPanels.d.ts | 17 ++++++++ .../plugins/toc/api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../tests/support/plugins/toc/api/types.ts | 42 +++++++++++++++++++ .../tests/support/plugins/toc/package.json | 17 ++++---- .../support/plugins/toc/webpack.config.js | 14 ++++++- .../withExternalModules/api/Joplin.d.ts | 11 ++--- .../api/JoplinCommands.d.ts | 10 ++--- .../withExternalModules/api/JoplinData.d.ts | 3 ++ .../api/JoplinFilters.d.ts | 4 +- .../api/JoplinInterop.d.ts | 4 +- .../api/JoplinSettings.d.ts | 2 +- .../api/JoplinViewsDialogs.d.ts | 3 +- .../api/JoplinViewsPanels.d.ts | 17 ++++++++ .../api/JoplinWorkspace.d.ts | 26 ++++++++++-- .../plugins/withExternalModules/api/types.ts | 42 +++++++++++++++++++ .../plugins/withExternalModules/package.json | 17 ++++---- .../withExternalModules/webpack.config.js | 14 ++++++- .../generators/app/templates/api/Joplin.d.ts | 5 ++- .../app/templates/api/JoplinCommands.d.ts | 8 ++-- .../app/templates/api/JoplinFilters.d.ts | 4 +- .../app/templates/api/JoplinInterop.d.ts | 4 +- .../app/templates/api/JoplinSettings.d.ts | 2 +- .../app/templates/api/JoplinWorkspace.d.ts | 10 ++--- .../generators/app/templates/api/types.ts | 6 +++ 211 files changed, 2074 insertions(+), 559 deletions(-) diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/types.ts b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/api/types.ts +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/package.json b/packages/app-cli/tests/support/plugins/codemirror_content_script/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/package.json +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/codemirror_content_script/webpack.config.js b/packages/app-cli/tests/support/plugins/codemirror_content_script/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/codemirror_content_script/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/codemirror_content_script/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/content_script/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/content_script/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/content_script/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/content_script/api/types.ts b/packages/app-cli/tests/support/plugins/content_script/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/content_script/api/types.ts +++ b/packages/app-cli/tests/support/plugins/content_script/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/content_script/package.json b/packages/app-cli/tests/support/plugins/content_script/package.json index 4098695b0..76ca0e47c 100644 --- a/packages/app-cli/tests/support/plugins/content_script/package.json +++ b/packages/app-cli/tests/support/plugins/content_script/package.json @@ -14,18 +14,21 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" + "chalk": "^4.1.0", + "yargs": "^16.2.0" }, "dependencies": { "left-pad": "1.3.0" - } -} \ No newline at end of file + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/content_script/webpack.config.js b/packages/app-cli/tests/support/plugins/content_script/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/content_script/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/content_script/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/dialog/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/dialog/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/dialog/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/dialog/api/types.ts b/packages/app-cli/tests/support/plugins/dialog/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/dialog/api/types.ts +++ b/packages/app-cli/tests/support/plugins/dialog/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/dialog/package.json b/packages/app-cli/tests/support/plugins/dialog/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/dialog/package.json +++ b/packages/app-cli/tests/support/plugins/dialog/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/dialog/webpack.config.js b/packages/app-cli/tests/support/plugins/dialog/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/dialog/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/dialog/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/api/types.ts b/packages/app-cli/tests/support/plugins/editor_context_menu/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/api/types.ts +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/package.json b/packages/app-cli/tests/support/plugins/editor_context_menu/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/package.json +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/editor_context_menu/webpack.config.js b/packages/app-cli/tests/support/plugins/editor_context_menu/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/editor_context_menu/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/editor_context_menu/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/events/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/events/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/events/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/events/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/events/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/events/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/events/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/events/api/types.ts b/packages/app-cli/tests/support/plugins/events/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/events/api/types.ts +++ b/packages/app-cli/tests/support/plugins/events/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/events/package.json b/packages/app-cli/tests/support/plugins/events/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/events/package.json +++ b/packages/app-cli/tests/support/plugins/events/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/events/webpack.config.js b/packages/app-cli/tests/support/plugins/events/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/events/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/events/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/external_assets/api/types.ts b/packages/app-cli/tests/support/plugins/external_assets/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/api/types.ts +++ b/packages/app-cli/tests/support/plugins/external_assets/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/external_assets/package.json b/packages/app-cli/tests/support/plugins/external_assets/package.json index ce2a4b825..7191a2964 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/package.json +++ b/packages/app-cli/tests/support/plugins/external_assets/package.json @@ -12,16 +12,19 @@ ], "devDependencies": { "@types/node": "^14.0.14", - "chalk": "4.1.2", + "chalk": "^4.1.0", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "yargs": "16.2.0" - } -} \ No newline at end of file + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/external_assets/webpack.config.js b/packages/app-cli/tests/support/plugins/external_assets/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/external_assets/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/external_assets/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/jpl_test/api/types.ts b/packages/app-cli/tests/support/plugins/jpl_test/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/api/types.ts +++ b/packages/app-cli/tests/support/plugins/jpl_test/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/jpl_test/package.json b/packages/app-cli/tests/support/plugins/jpl_test/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/package.json +++ b/packages/app-cli/tests/support/plugins/jpl_test/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/jpl_test/webpack.config.js b/packages/app-cli/tests/support/plugins/jpl_test/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/jpl_test/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/jpl_test/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/json_export/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/json_export/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/json_export/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/json_export/api/types.ts b/packages/app-cli/tests/support/plugins/json_export/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/json_export/api/types.ts +++ b/packages/app-cli/tests/support/plugins/json_export/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/json_export/package.json b/packages/app-cli/tests/support/plugins/json_export/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/json_export/package.json +++ b/packages/app-cli/tests/support/plugins/json_export/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/json_export/webpack.config.js b/packages/app-cli/tests/support/plugins/json_export/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/json_export/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/json_export/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/menu/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/menu/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/menu/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/menu/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/menu/api/types.ts b/packages/app-cli/tests/support/plugins/menu/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/menu/api/types.ts +++ b/packages/app-cli/tests/support/plugins/menu/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/menu/package.json b/packages/app-cli/tests/support/plugins/menu/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/menu/package.json +++ b/packages/app-cli/tests/support/plugins/menu/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/menu/webpack.config.js b/packages/app-cli/tests/support/plugins/menu/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/menu/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/menu/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/multi_selection/api/types.ts b/packages/app-cli/tests/support/plugins/multi_selection/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/api/types.ts +++ b/packages/app-cli/tests/support/plugins/multi_selection/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/multi_selection/package.json b/packages/app-cli/tests/support/plugins/multi_selection/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/package.json +++ b/packages/app-cli/tests/support/plugins/multi_selection/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/multi_selection/webpack.config.js b/packages/app-cli/tests/support/plugins/multi_selection/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/multi_selection/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/multi_selection/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/nativeModule/api/types.ts b/packages/app-cli/tests/support/plugins/nativeModule/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/api/types.ts +++ b/packages/app-cli/tests/support/plugins/nativeModule/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/nativeModule/package.json b/packages/app-cli/tests/support/plugins/nativeModule/package.json index 2ad6383a3..eeb5b8ec6 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/package.json +++ b/packages/app-cli/tests/support/plugins/nativeModule/package.json @@ -12,16 +12,19 @@ ], "devDependencies": { "@types/node": "^14.0.14", - "chalk": "4.1.2", + "chalk": "^4.1.0", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "yargs": "16.2.0" - } -} \ No newline at end of file + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/nativeModule/webpack.config.js b/packages/app-cli/tests/support/plugins/nativeModule/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/nativeModule/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/nativeModule/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/post_messages/api/types.ts b/packages/app-cli/tests/support/plugins/post_messages/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/api/types.ts +++ b/packages/app-cli/tests/support/plugins/post_messages/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/post_messages/package.json b/packages/app-cli/tests/support/plugins/post_messages/package.json index 6c22fa9af..ee443f3bb 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/package.json +++ b/packages/app-cli/tests/support/plugins/post_messages/package.json @@ -12,16 +12,19 @@ ], "devDependencies": { "@types/node": "^14.0.14", - "chalk": "4.1.2", + "chalk": "^4.1.0", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "yargs": "16.2.0" - } -} \ No newline at end of file + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/post_messages/webpack.config.js b/packages/app-cli/tests/support/plugins/post_messages/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/post_messages/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/post_messages/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/register_command/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/register_command/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/register_command/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/register_command/api/types.ts b/packages/app-cli/tests/support/plugins/register_command/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/register_command/api/types.ts +++ b/packages/app-cli/tests/support/plugins/register_command/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/register_command/package.json b/packages/app-cli/tests/support/plugins/register_command/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/register_command/package.json +++ b/packages/app-cli/tests/support/plugins/register_command/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/register_command/webpack.config.js b/packages/app-cli/tests/support/plugins/register_command/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/register_command/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/register_command/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/selected_text/api/types.ts b/packages/app-cli/tests/support/plugins/selected_text/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/api/types.ts +++ b/packages/app-cli/tests/support/plugins/selected_text/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/selected_text/package.json b/packages/app-cli/tests/support/plugins/selected_text/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/package.json +++ b/packages/app-cli/tests/support/plugins/selected_text/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/selected_text/webpack.config.js b/packages/app-cli/tests/support/plugins/selected_text/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/selected_text/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/selected_text/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/settings/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/settings/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/settings/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/settings/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/settings/api/types.ts b/packages/app-cli/tests/support/plugins/settings/api/types.ts index 3b9082aed..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/settings/api/types.ts +++ b/packages/app-cli/tests/support/plugins/settings/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -356,6 +386,11 @@ export enum SettingStorage { export interface SettingItem { value: any; type: SettingItemType; + + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ subType?: SettingItemSubType; label: string; diff --git a/packages/app-cli/tests/support/plugins/settings/package.json b/packages/app-cli/tests/support/plugins/settings/package.json index 86a19b0f5..7308887ae 100644 --- a/packages/app-cli/tests/support/plugins/settings/package.json +++ b/packages/app-cli/tests/support/plugins/settings/package.json @@ -14,15 +14,18 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" - } -} \ No newline at end of file + "chalk": "^4.1.0", + "yargs": "^16.2.0" + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/settings/webpack.config.js b/packages/app-cli/tests/support/plugins/settings/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/settings/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/settings/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/toc/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/toc/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/toc/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/toc/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/toc/api/types.ts b/packages/app-cli/tests/support/plugins/toc/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/toc/api/types.ts +++ b/packages/app-cli/tests/support/plugins/toc/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/toc/package.json b/packages/app-cli/tests/support/plugins/toc/package.json index dee6c93b5..b64d4c4d1 100644 --- a/packages/app-cli/tests/support/plugins/toc/package.json +++ b/packages/app-cli/tests/support/plugins/toc/package.json @@ -14,18 +14,21 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" + "chalk": "^4.1.0", + "yargs": "^16.2.0" }, "dependencies": { "uslug": "^1.0.4" - } -} \ No newline at end of file + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/toc/webpack.config.js b/packages/app-cli/tests/support/plugins/toc/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/toc/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/toc/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/Joplin.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/Joplin.d.ts index 09d856e37..c3a0200d0 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/Joplin.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/Joplin.d.ts @@ -13,17 +13,14 @@ import JoplinWindow from './JoplinWindow'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * - * **This is a beta API** + * The API is now relatively stable and in general maintaining backward compatibility is a top priority, so you shouldn't except much breakages. * - * 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: + * If a breaking change ever becomes needed, best effort will be done to: * - * - Maintain backward compatibility; - * - When possible, deprecate features instead of removing them; + * - Deprecate features instead of removing them, so as to give you time to fix the issue; * - 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. + * 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. */ export default class Joplin { private data_; diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinCommands.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinCommands.d.ts index e4487cf33..babb249c5 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinCommands.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinCommands.d.ts @@ -15,7 +15,7 @@ import { Command } from './types'; * * * [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) + * * [Editor commands](https://github.com/laurent22/joplin/tree/dev/packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts) * * To view what arguments are supported, you can open any of these files * and look at the `execute()` command. @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinData.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinData.d.ts index fbde6ff9a..c257ad558 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinData.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinData.d.ts @@ -1,3 +1,4 @@ +import { ModelType } from '../../../BaseModel'; import { Path } from './types'; /** * This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/ @@ -44,4 +45,6 @@ export default class JoplinData { post(path: Path, query?: any, body?: any, files?: any[]): Promise; put(path: Path, query?: any, body?: any, files?: any[]): Promise; delete(path: Path, query?: any): Promise; + itemType(itemId: string): Promise; + resourcePath(resourceId: string): Promise; } diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinFilters.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinFilters.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinInterop.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinInterop.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinSettings.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinSettings.d.ts index a22b9073c..74572b7ab 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinSettings.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export declare type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsDialogs.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsDialogs.d.ts index f1643a01d..8bc988739 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsDialogs.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsDialogs.d.ts @@ -61,8 +61,7 @@ export default class JoplinViewsDialogs { open(handle: ViewHandle): Promise; /** * Toggle on whether to fit the dialog size to the content or not. - * When set to false, the dialog stretches to fill the application - * window. + * When set to false, the dialog is set to 90vw and 80vh * @default true */ setFitToContent(handle: ViewHandle, status: boolean): Promise; diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsPanels.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsPanels.d.ts index 20d3e1264..4d4c52701 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsPanels.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinViewsPanels.d.ts @@ -46,6 +46,23 @@ export default class JoplinViewsPanels { * */ onMessage(handle: ViewHandle, callback: Function): Promise; + /** + * Sends a message to the webview. + * + * The webview must have registered a message handler prior, otherwise the message is ignored. Use; + * + * ```javascript + * webviewApi.onMessage((message) => { ... }); + * ``` + * + * - `message` can be any JavaScript object, string or number + * + * The view API may have only one onMessage handler defined. + * This method is fire and forget so no response is returned. + * + * It is particularly useful when the webview needs to react to events emitted by the plugin or the joplin api. + */ + postMessage(handle: ViewHandle, message: any): void; /** * Shows the panel */ diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinWorkspace.d.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinWorkspace.d.ts index 229175713..0a12e26ed 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinWorkspace.d.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/JoplinWorkspace.d.ts @@ -1,9 +1,13 @@ import { FolderEntity } from '../../database/types'; -import { Disposable } from './types'; +import { Disposable, MenuItem } from './types'; +export interface EditContextMenuFilterObject { + items: MenuItem[]; +} +declare type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -12,8 +16,12 @@ interface ItemChangeEvent { interface SyncStartEvent { withErrors: boolean; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; +interface ResourceChangeEvent { + id: string; +} +declare type ItemChangeHandler = (event: ItemChangeEvent) => void; +declare type SyncStartHandler = (event: SyncStartEvent) => void; +declare type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 @@ -38,6 +46,11 @@ export default class JoplinWorkspace { * Called when the content of the current note changes. */ onNoteChange(handler: ItemChangeHandler): Promise; + /** + * Called when a resource is changed. Currently this handled will not be + * called when a resource is added or deleted. + */ + onResourceChange(handler: ResourceChangeHandler): Promise; /** * Called when an alarm associated with a to-do is triggered. */ @@ -50,6 +63,11 @@ export default class JoplinWorkspace { * Called when the synchronisation process has finished. */ onSyncComplete(callback: Function): Promise; + /** + * Called just before the editor context menu is about to open. Allows + * adding items to it. + */ + filterEditorContextMenu(handler: FilterHandler): void; /** * Gets the currently selected note */ diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/api/types.ts b/packages/app-cli/tests/support/plugins/withExternalModules/api/types.ts index e0b2d96c0..640d08399 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/api/types.ts +++ b/packages/app-cli/tests/support/plugins/withExternalModules/api/types.ts @@ -202,6 +202,25 @@ export interface Disposable { // dispose():void; } +export enum ModelType { + Note = 1, + Folder = 2, + Setting = 3, + Resource = 4, + Tag = 5, + NoteTag = 6, + Search = 7, + Alarm = 8, + MasterKey = 9, + ItemChange = 10, + NoteResource = 11, + ResourceLocalState = 12, + Revision = 13, + Migration = 14, + SmartFilter = 15, + Command = 16, +} + // ================================================================= // Menu types // ================================================================= @@ -269,6 +288,17 @@ export interface MenuItem { */ commandName?: string; + /** + * Arguments that should be passed to the command. They will be as rest + * parameters. + */ + commandArgs?: any[]; + + /** + * Set to "separator" to create a divider line + */ + type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'); + /** * Accelerator associated with the menu item */ @@ -334,6 +364,12 @@ export enum SettingItemType { Button = 6, } +export enum SettingItemSubType { + FilePathAndArgs = 'file_path_and_args', + FilePath = 'file_path', // Not supported on mobile! + DirectoryPath = 'directory_path', // Not supported on mobile! +} + export enum AppType { Desktop = 'desktop', Mobile = 'mobile', @@ -351,6 +387,12 @@ export interface SettingItem { value: any; type: SettingItemType; + /** + * Currently only used to display a file or directory selector. Always set + * `type` to `SettingItemType.String` when using this property. + */ + subType?: SettingItemSubType; + label: string; description?: string; diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/package.json b/packages/app-cli/tests/support/plugins/withExternalModules/package.json index 4098695b0..76ca0e47c 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/package.json +++ b/packages/app-cli/tests/support/plugins/withExternalModules/package.json @@ -14,18 +14,21 @@ "devDependencies": { "@types/node": "^14.0.14", "copy-webpack-plugin": "^6.1.0", - "fs-extra": "9.1.0", - "glob": "7.2.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", "on-build-webpack": "^0.1.0", - "tar": "6.1.11", + "tar": "^6.0.5", "ts-loader": "^7.0.5", "typescript": "^3.9.3", "webpack": "^4.43.0", "webpack-cli": "^3.3.11", - "chalk": "4.1.2", - "yargs": "16.2.0" + "chalk": "^4.1.0", + "yargs": "^16.2.0" }, "dependencies": { "left-pad": "1.3.0" - } -} \ No newline at end of file + }, + "files": [ + "publish" + ] +} \ No newline at end of file diff --git a/packages/app-cli/tests/support/plugins/withExternalModules/webpack.config.js b/packages/app-cli/tests/support/plugins/withExternalModules/webpack.config.js index d6052c5db..1c2d7e7bf 100644 --- a/packages/app-cli/tests/support/plugins/withExternalModules/webpack.config.js +++ b/packages/app-cli/tests/support/plugins/withExternalModules/webpack.config.js @@ -29,6 +29,7 @@ const userConfig = Object.assign({}, { const manifestPath = `${srcDir}/manifest.json`; const packageJsonPath = `${rootDir}/package.json`; +const allPossibleCategories = ['appearance', 'developer tools', 'productivity', 'themes', 'integrations', 'viewer', 'search', 'tags', 'editor', 'files', 'personal knowledge management']; const manifest = readManifest(manifestPath); const pluginArchiveFilePath = path.resolve(publishDir, `${manifest.id}.jpl`); const pluginInfoFilePath = path.resolve(publishDir, `${manifest.id}.json`); @@ -67,10 +68,19 @@ function currentGitInfo() { } } +function validateCategories(categories) { + if (!categories) return null; + if ((categories.length !== new Set(categories).size)) throw new Error('Repeated categories are not allowed'); + categories.forEach(category => { + if (!allPossibleCategories.includes(category)) throw new Error(`${category} is not a valid category. Please make sure that the category name is lowercase. Valid Categories are: \n${allPossibleCategories}\n`); + }); +} + function readManifest(manifestPath) { const content = fs.readFileSync(manifestPath, 'utf8'); const output = JSON.parse(content); if (!output.id) throw new Error(`Manifest plugin ID is not set in ${manifestPath}`); + validateCategories(output.categories); return output; } @@ -137,7 +147,7 @@ const pluginConfig = Object.assign({}, baseConfig, { }, // JSON files can also be required from scripts so we include this. // https://github.com/joplin/plugin-bibtex/pull/2 - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, output: { filename: 'index.js', @@ -169,7 +179,7 @@ const extraScriptConfig = Object.assign({}, baseConfig, { alias: { api: path.resolve(__dirname, 'api'), }, - extensions: ['.tsx', '.ts', '.js', '.json'], + extensions: ['.js', '.tsx', '.ts', '.json'], }, }); diff --git a/packages/generator-joplin/generators/app/templates/api/Joplin.d.ts b/packages/generator-joplin/generators/app/templates/api/Joplin.d.ts index c3a0200d0..011168320 100644 --- a/packages/generator-joplin/generators/app/templates/api/Joplin.d.ts +++ b/packages/generator-joplin/generators/app/templates/api/Joplin.d.ts @@ -10,6 +10,7 @@ import JoplinSettings from './JoplinSettings'; import JoplinContentScripts from './JoplinContentScripts'; import JoplinClipboard from './JoplinClipboard'; import JoplinWindow from './JoplinWindow'; +import BasePlatformImplementation from '../BasePlatformImplementation'; /** * This is the main entry point to the Joplin API. You can access various services using the provided accessors. * @@ -34,7 +35,8 @@ export default class Joplin { private contentScripts_; private clipboard_; private window_; - constructor(implementation: any, plugin: Plugin, store: any); + private implementation_; + constructor(implementation: BasePlatformImplementation, plugin: Plugin, store: any); get data(): JoplinData; get clipboard(): JoplinClipboard; get window(): JoplinWindow; @@ -65,4 +67,5 @@ export default class Joplin { * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/nativeModule) */ require(_path: string): any; + versionInfo(): Promise; } diff --git a/packages/generator-joplin/generators/app/templates/api/JoplinCommands.d.ts b/packages/generator-joplin/generators/app/templates/api/JoplinCommands.d.ts index 031cc9234..babb249c5 100644 --- a/packages/generator-joplin/generators/app/templates/api/JoplinCommands.d.ts +++ b/packages/generator-joplin/generators/app/templates/api/JoplinCommands.d.ts @@ -49,7 +49,7 @@ import { Command } from './types'; * */ export default class JoplinCommands { - /** + /** * desktop Executes the given * command. * @@ -68,8 +68,8 @@ export default class JoplinCommands { * await joplin.commands.execute('newFolder', "SOME_FOLDER_ID"); * ``` */ - execute(commandName: string, ...args: any[]): Promise; - /** + execute(commandName: string, ...args: any[]): Promise; + /** * desktop Registers a new command. * * ```typescript @@ -85,5 +85,5 @@ export default class JoplinCommands { * }); * ``` */ - register(command: Command): Promise; + register(command: Command): Promise; } diff --git a/packages/generator-joplin/generators/app/templates/api/JoplinFilters.d.ts b/packages/generator-joplin/generators/app/templates/api/JoplinFilters.d.ts index e086a720e..43bc1b2b7 100644 --- a/packages/generator-joplin/generators/app/templates/api/JoplinFilters.d.ts +++ b/packages/generator-joplin/generators/app/templates/api/JoplinFilters.d.ts @@ -5,6 +5,6 @@ * so for now disable filters. */ export default class JoplinFilters { - on(name: string, callback: Function): Promise; - off(name: string, callback: Function): Promise; + on(name: string, callback: Function): Promise; + off(name: string, callback: Function): Promise; } diff --git a/packages/generator-joplin/generators/app/templates/api/JoplinInterop.d.ts b/packages/generator-joplin/generators/app/templates/api/JoplinInterop.d.ts index 1304c7512..8de655c83 100644 --- a/packages/generator-joplin/generators/app/templates/api/JoplinInterop.d.ts +++ b/packages/generator-joplin/generators/app/templates/api/JoplinInterop.d.ts @@ -12,6 +12,6 @@ import { ExportModule, ImportModule } from './types'; * You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/ */ export default class JoplinInterop { - registerExportModule(module: ExportModule): Promise; - registerImportModule(module: ImportModule): Promise; + registerExportModule(module: ExportModule): Promise; + registerImportModule(module: ImportModule): Promise; } diff --git a/packages/generator-joplin/generators/app/templates/api/JoplinSettings.d.ts b/packages/generator-joplin/generators/app/templates/api/JoplinSettings.d.ts index a22b9073c..32ce9d4cb 100644 --- a/packages/generator-joplin/generators/app/templates/api/JoplinSettings.d.ts +++ b/packages/generator-joplin/generators/app/templates/api/JoplinSettings.d.ts @@ -6,7 +6,7 @@ export interface ChangeEvent { */ keys: string[]; } -export declare type ChangeHandler = (event: ChangeEvent)=> void; +export type ChangeHandler = (event: ChangeEvent) => void; /** * This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user. * diff --git a/packages/generator-joplin/generators/app/templates/api/JoplinWorkspace.d.ts b/packages/generator-joplin/generators/app/templates/api/JoplinWorkspace.d.ts index 5fdd284eb..626d6b6a8 100644 --- a/packages/generator-joplin/generators/app/templates/api/JoplinWorkspace.d.ts +++ b/packages/generator-joplin/generators/app/templates/api/JoplinWorkspace.d.ts @@ -3,11 +3,11 @@ import { Disposable, MenuItem } from './types'; export interface EditContextMenuFilterObject { items: MenuItem[]; } -declare type FilterHandler = (object: T)=> Promise; +type FilterHandler = (object: T) => Promise; declare enum ItemChangeEventType { Create = 1, Update = 2, - Delete = 3, + Delete = 3 } interface ItemChangeEvent { id: string; @@ -19,9 +19,9 @@ interface SyncStartEvent { interface ResourceChangeEvent { id: string; } -declare type ItemChangeHandler = (event: ItemChangeEvent)=> void; -declare type SyncStartHandler = (event: SyncStartEvent)=> void; -declare type ResourceChangeHandler = (event: ResourceChangeEvent)=> void; +type ItemChangeHandler = (event: ItemChangeEvent) => void; +type SyncStartHandler = (event: SyncStartEvent) => void; +type ResourceChangeHandler = (event: ResourceChangeEvent) => void; /** * 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 diff --git a/packages/generator-joplin/generators/app/templates/api/types.ts b/packages/generator-joplin/generators/app/templates/api/types.ts index 640d08399..f8ac2cf29 100644 --- a/packages/generator-joplin/generators/app/templates/api/types.ts +++ b/packages/generator-joplin/generators/app/templates/api/types.ts @@ -221,6 +221,12 @@ export enum ModelType { Command = 16, } +export interface VersionInfo { + version: string; + profileVersion: number; + syncVersion: number; +} + // ================================================================= // Menu types // =================================================================