1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-07-16 00:14:34 +02:00

Plugins: Add support for context menu items on notebooks and tags

This commit is contained in:
Laurent Cozic
2020-12-11 13:28:59 +00:00
parent a1c08adb3e
commit 9f8e6a3060
83 changed files with 2600 additions and 503 deletions

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -35,6 +35,22 @@ joplin.plugins.register({
}, },
}); });
await joplin.commands.register({
name: 'folderContextMenuExample',
label: 'Folder menu item from plugin',
execute: async (folderId:string) => {
console.info('Click on folder: ' + folderId);
},
});
await joplin.commands.register({
name: 'tagContextMenuExample',
label: 'Tag menu item from plugin',
execute: async (tagId:string) => {
console.info('Click on tag: ' + tagId);
},
});
// Commands that return a result and take argument can only be used // Commands that return a result and take argument can only be used
// programmatically, so it's not necessary to set a label and icon. // programmatically, so it's not necessary to set a label and icon.
await joplin.commands.register({ await joplin.commands.register({
@ -56,6 +72,9 @@ joplin.plugins.register({
await joplin.views.menuItems.create('contextMenuItem1', 'contextMenuCommandExample', MenuItemLocation.NoteListContextMenu); await joplin.views.menuItems.create('contextMenuItem1', 'contextMenuCommandExample', MenuItemLocation.NoteListContextMenu);
await joplin.views.menuItems.create('folderMenuItem1', 'folderContextMenuExample', MenuItemLocation.FolderContextMenu);
await joplin.views.menuItems.create('tagMenuItem1', 'tagContextMenuExample', MenuItemLocation.TagContextMenu);
console.info('Running command with arguments...'); console.info('Running command with arguments...');
const result = await joplin.commands.execute('commandWithResult', 'abcd', 123); const result = await joplin.commands.execute('commandWithResult', 'abcd', 123);
console.info('Result was: ' + result); console.info('Result was: ' + result);

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent) => void;
declare type SyncStartHandler = (event: SyncStartEvent) => 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -13,7 +13,7 @@ function readManifest(manifestPath) {
} }
function createPluginArchive(sourceDir, destPath) { function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`) const distFiles = glob.sync(`${sourceDir}/**/*`, { nodir: true })
.map(f => f.substr(sourceDir.length + 1)); .map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) { if (!distFiles.length) {

View File

@ -12,7 +12,7 @@ import versionInfo from '@joplin/lib/versionInfo';
import { Module } from '@joplin/lib/services/interop/types'; import { Module } from '@joplin/lib/services/interop/types';
import InteropServiceHelper from '../InteropServiceHelper'; import InteropServiceHelper from '../InteropServiceHelper';
import { _ } from '@joplin/lib/locale'; import { _ } from '@joplin/lib/locale';
import { MenuItem, MenuItemLocation } from '@joplin/lib/services/plugins/api/types'; import { isContextMenuItemLocation, MenuItem, MenuItemLocation } from '@joplin/lib/services/plugins/api/types';
import SpellCheckerService from '@joplin/lib/services/spellChecker/SpellCheckerService'; import SpellCheckerService from '@joplin/lib/services/spellChecker/SpellCheckerService';
import menuCommandNames from './menuCommandNames'; import menuCommandNames from './menuCommandNames';
import stateToWhenClauseContext from '../services/commands/stateToWhenClauseContext'; import stateToWhenClauseContext from '../services/commands/stateToWhenClauseContext';
@ -697,7 +697,7 @@ function useMenu(props: Props) {
for (const view of props.pluginMenuItems) { for (const view of props.pluginMenuItems) {
const location: MenuItemLocation = view.location; const location: MenuItemLocation = view.location;
if ([MenuItemLocation.Context, MenuItemLocation.EditorContextMenu, MenuItemLocation.NoteListContextMenu].includes(location)) continue; if (isContextMenuItemLocation(location)) continue;
const itemParent = rootMenus[location]; const itemParent = rootMenus[location];
@ -709,7 +709,7 @@ function useMenu(props: Props) {
} }
for (const view of props.pluginMenus) { for (const view of props.pluginMenus) {
if ([MenuItemLocation.Context, MenuItemLocation.EditorContextMenu, MenuItemLocation.NoteListContextMenu].includes(view.location)) continue; if (isContextMenuItemLocation(view.location)) continue;
const itemParent = rootMenus[view.location]; const itemParent = rootMenus[view.location];
if (!itemParent) { if (!itemParent) {

View File

@ -8,6 +8,10 @@ import Setting from '@joplin/lib/models/Setting';
import MenuUtils from '@joplin/lib/services/commands/MenuUtils'; import MenuUtils from '@joplin/lib/services/commands/MenuUtils';
import InteropServiceHelper from '../../InteropServiceHelper'; import InteropServiceHelper from '../../InteropServiceHelper';
import { _ } from '@joplin/lib/locale'; import { _ } from '@joplin/lib/locale';
import { PluginStates, utils as pluginUtils } from '@joplin/lib/services/plugins/reducer';
import { MenuItemLocation } from '@joplin/lib/services/plugins/api/types';
import { AppState } from '../../app';
import { ModelType } from '@joplin/lib/BaseModel';
const { connect } = require('react-redux'); const { connect } = require('react-redux');
const shared = require('@joplin/lib/components/shared/side-menu-shared.js'); const shared = require('@joplin/lib/components/shared/side-menu-shared.js');
@ -36,6 +40,7 @@ interface Props {
syncReport: any; syncReport: any;
tags: any[]; tags: any[];
syncStarted: boolean; syncStarted: boolean;
plugins: PluginStates;
} }
interface State { interface State {
@ -101,6 +106,7 @@ class SideBarComponent extends React.Component<Props, State> {
private tagItemsOrder_: any[] = []; private tagItemsOrder_: any[] = [];
private rootRef: any = null; private rootRef: any = null;
private anchorItemRefs: any = {}; private anchorItemRefs: any = {};
private pluginsRef: any;
constructor(props: any) { constructor(props: any) {
super(props); super(props);
@ -112,6 +118,14 @@ class SideBarComponent extends React.Component<Props, State> {
folderHeaderIsExpanded: Setting.value('folderHeaderIsExpanded'), folderHeaderIsExpanded: Setting.value('folderHeaderIsExpanded'),
}; };
// This whole component is a bit of a mess and rather than passing
// a plugins prop around, not knowing how it's going to affect
// re-rendering, we just keep a ref to it. Currently that's enough
// as plugins are only accessed from context menus. However if want
// to do more complex things with plugins in the sidebar, it will
// probably have to be refactored using React Hooks first.
this.pluginsRef = React.createRef();
this.onFolderToggleClick_ = this.onFolderToggleClick_.bind(this); this.onFolderToggleClick_ = this.onFolderToggleClick_.bind(this);
this.onKeyDown = this.onKeyDown.bind(this); this.onKeyDown = this.onKeyDown.bind(this);
this.onAllNotesClick_ = this.onAllNotesClick_.bind(this); this.onAllNotesClick_ = this.onAllNotesClick_.bind(this);
@ -294,6 +308,20 @@ class SideBarComponent extends React.Component<Props, State> {
)); ));
} }
const pluginViews = pluginUtils.viewsByType(this.pluginsRef.current, 'menuItem');
for (const view of pluginViews) {
const location = view.location;
if (itemType === ModelType.Tag && location === MenuItemLocation.TagContextMenu ||
itemType === ModelType.Folder && location === MenuItemLocation.FolderContextMenu
) {
menu.append(
new MenuItem(menuUtils.commandToStatefulMenuItem(view.commandName, itemId))
);
}
}
menu.popup(bridge().window()); menu.popup(bridge().window());
} }
@ -584,6 +612,8 @@ class SideBarComponent extends React.Component<Props, State> {
// } // }
render() { render() {
this.pluginsRef.current = this.props.plugins;
const theme = themeStyle(this.props.themeId); const theme = themeStyle(this.props.themeId);
const items = []; const items = [];
@ -668,7 +698,7 @@ class SideBarComponent extends React.Component<Props, State> {
} }
} }
const mapStateToProps = (state: any) => { const mapStateToProps = (state: AppState) => {
return { return {
folders: state.folders, folders: state.folders,
tags: state.tags, tags: state.tags,
@ -685,6 +715,7 @@ const mapStateToProps = (state: any) => {
collapsedFolderIds: state.collapsedFolderIds, collapsedFolderIds: state.collapsedFolderIds,
decryptionWorker: state.decryptionWorker, decryptionWorker: state.decryptionWorker,
resourceFetcher: state.resourceFetcher, resourceFetcher: state.resourceFetcher,
plugins: state.pluginService.plugins,
}; };
}; };

View File

@ -4,5 +4,5 @@
# It could be used to develop plugins too. # It could be used to develop plugins too.
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
PLUGIN_PATH="$SCRIPT_DIR/../app-cli/tests/support/plugins/editor_context_menu" PLUGIN_PATH="$SCRIPT_DIR/../app-cli/tests/support/plugins/register_command"
npm i --prefix="$PLUGIN_PATH" && npm start -- --dev-plugins "$PLUGIN_PATH" npm i --prefix="$PLUGIN_PATH" && npm start -- --dev-plugins "$PLUGIN_PATH"

View File

@ -20,14 +20,20 @@ export default class JoplinPlugins {
*/ */
register(script: Script): Promise<void>; register(script: Script): Promise<void>;
/** /**
* Registers a new content script. Unlike regular plugin code, which runs in a separate process, content scripts run within the main process code * Registers a new content script. Unlike regular plugin code, which
* and thus allow improved performances and more customisations in specific cases. It can be used for example to load a Markdown or editor plugin. * runs in a separate process, content scripts run within the main
* process code and thus allow improved performances and more
* customisations in specific cases. It can be used for example to load
* a Markdown or editor plugin.
* *
* Note that registering a content script in itself will do nothing - it will only be loaded in specific cases by the relevant app modules * Note that registering a content script in itself will do nothing -
* (eg. the Markdown renderer or the code editor). So it is not a way to inject and run arbitrary code in the app, which for safety and performance reasons is not supported. * it will only be loaded in specific cases by the relevant app modules
* (eg. the Markdown renderer or the code editor). So it is not a way
* to inject and run arbitrary code in the app, which for safety and
* performance reasons is not supported.
* *
* [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script) * * [View the renderer demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) * * [View the editor demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* *
* @param type Defines how the script will be used. See the type definition for more information about each supported type. * @param type Defines how the script will be used. See the type definition for more information about each supported type.
* @param id A unique ID for the content script. * @param id A unique ID for the content script.

View File

@ -37,7 +37,7 @@ export default class JoplinSettings {
* *
* The list of available settings is not documented yet, but can be found by looking at the source code: * The list of available settings is not documented yet, but can be found by looking at the source code:
* *
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/packages/app-mobile/lib/models/Setting.ts#L142 * https://github.com/laurent22/joplin/blob/dev/packages/lib/models/Setting.ts#L142
*/ */
globalValue(key: string): Promise<any>; globalValue(key: string): Promise<any>;
} }

View File

@ -1,28 +1,54 @@
import { Disposable } from './types';
declare enum ItemChangeEventType {
Create = 1,
Update = 2,
Delete = 3,
}
interface ItemChangeEvent {
id: string;
event: ItemChangeEventType;
}
interface SyncStartEvent {
withErrors: boolean;
}
declare type ItemChangeHandler = (event: ItemChangeEvent)=> void;
declare type SyncStartHandler = (event: SyncStartEvent)=> 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 well * The workspace service provides access to all the parts of Joplin that
* as various related events, such as when a new note is selected, or when the note content changes. * are being worked on - i.e. the currently selected notes or notebooks as
* well as various related events, such as when a new note is selected, or
* when the note content changes.
* *
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) * [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
*/ */
export default class JoplinWorkspace { export default class JoplinWorkspace {
private store; private store;
constructor(_implementation: any, store: any); constructor(store: any);
/** /**
* Called when a new note or notes are selected. * Called when a new note or notes are selected.
*/ */
onNoteSelectionChange(callback: Function): Promise<void>; onNoteSelectionChange(callback: Function): Promise<Disposable>;
/** /**
* Called when the content of a note changes. * Called when the content of a note changes.
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
*/ */
onNoteContentChange(callback: Function): Promise<void>; onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteChange(handler: ItemChangeHandler): Promise<Disposable>;
/** /**
* Called when an alarm associated with a to-do is triggered. * Called when an alarm associated with a to-do is triggered.
*/ */
onNoteAlarmTrigger(callback: Function): Promise<void>; onNoteAlarmTrigger(handler: Function): Promise<Disposable>;
/**
* Called when the synchronisation process is starting.
*/
onSyncStart(handler: SyncStartHandler): Promise<Disposable>;
/** /**
* Called when the synchronisation process has finished. * Called when the synchronisation process has finished.
*/ */
onSyncComplete(callback: Function): Promise<void>; onSyncComplete(callback: Function): Promise<Disposable>;
/** /**
* Gets the currently selected note * Gets the currently selected note
*/ */
@ -32,3 +58,4 @@ export default class JoplinWorkspace {
*/ */
selectedNoteIds(): Promise<string[]>; selectedNoteIds(): Promise<string[]>;
} }
export {};

View File

@ -40,7 +40,7 @@ export interface Command {
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted" * Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
* And | && | "oneNoteSelected && !inConflictFolder" * And | && | "oneNoteSelected && !inConflictFolder"
* *
* Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/services/commands/stateToWhenClauseContext.ts). * Currently the supported context variables aren't documented, but you can [find the list here](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* *
* Note: Commands are enabled by default unless you use this property. * Note: Commands are enabled by default unless you use this property.
*/ */
@ -189,6 +189,10 @@ export interface Script {
onStart?(event: any): Promise<void>; onStart?(event: any): Promise<void>;
} }
export interface Disposable {
// dispose():void;
}
// ================================================================= // =================================================================
// Menu types // Menu types
// ================================================================= // =================================================================
@ -204,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location: MenuItemLocation): boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {
@ -318,9 +359,9 @@ export interface SettingSection {
/** /**
* An array of at least one element and at most three elements. * An array of at least one element and at most three elements.
* *
* [0]: Resource name (eg. "notes", "folders", "tags", etc.) * - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID. * - **[1]**: (Optional) Resource ID.
* [2]: (Optional) Resource link. * - **[2]**: (Optional) Resource link.
*/ */
export type Path = string[]; export type Path = string[];
@ -330,7 +371,8 @@ export type Path = string[];
export enum ContentScriptType { export enum ContentScriptType {
/** /**
* Registers a new Markdown-It plugin, which should follow the template below. * Registers a new Markdown-It plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -346,14 +388,49 @@ export enum ContentScriptType {
* } * }
* } * }
* ``` * ```
* See [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* for a simple Markdown-it plugin example.
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * ## Exported members
* *
* - The **required** `plugin` key is the actual Markdown-It plugin - check the [official doc](https://github.com/markdown-it/markdown-it) for more information. The `options` parameter is of type [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml.ts), which contains a number of options, mostly useful for Joplin's internal code. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - Using the **optional** `assets` key you may specify assets such as JS or CSS that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - The **required** `plugin` key is the actual Markdown-It plugin -
* check the [official
* doc](https://github.com/markdown-it/markdown-it) for more
* information. The `options` parameter is of type
* [RuleOptions](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml.ts),
* which contains a number of options, mostly useful for Joplin's
* internal code.
* *
* To include a regular Markdown-It plugin, that doesn't make use of any Joplin-specific features, you would simply create a file such as this: * - Using the **optional** `assets` key you may specify assets such as
* JS or CSS that should be loaded in the rendered HTML document.
* Check for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
*
* ## Passing messages from the content script to your plugin
*
* The application provides the following function to allow executing
* commands from the rendered HTML code:
*
* `webviewApi.executeCommand(commandName, ...args)`
*
* So you can use this mechanism to pass messages from the note viewer
* to your own plugin. To do so you would define a command, using
* `joplin.commands.register`, then you would call this command using
* the `webviewApi` object. See again [the
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
* to see how this can be done.
*
* ## Registering an existing Markdown-it plugin
*
* To include a regular Markdown-It plugin, that doesn't make use of
* any Joplin-specific features, you would simply create a file such as
* this:
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -367,7 +444,8 @@ export enum ContentScriptType {
*/ */
MarkdownItPlugin = 'markdownItPlugin', MarkdownItPlugin = 'markdownItPlugin',
/** /**
* Registers a new CodeMirror plugin, which should follow the template below. * Registers a new CodeMirror plugin, which should follow the template
* below.
* *
* ```javascript * ```javascript
* module.exports = { * module.exports = {
@ -388,19 +466,42 @@ export enum ContentScriptType {
* } * }
* ``` * ```
* *
* - The `context` argument is currently unused but could be used later on to provide access to your own plugin so that the content script and plugin can communicate. * - The `context` argument is currently unused but could be used later
* on to provide access to your own plugin so that the content script
* and plugin can communicate.
* *
* - The `plugin` key is your CodeMirror plugin. This is where you can register new commands with CodeMirror or interact with the CodeMirror instance as needed. * - The `plugin` key is your CodeMirror plugin. This is where you can
* register new commands with CodeMirror or interact with the
* CodeMirror instance as needed.
* *
* - The `codeMirrorResources` key is an array of CodeMirror resources that will be loaded and attached to the CodeMirror module. These are made up of addons, keymaps, and modes. For example, for a plugin that want's to enable clojure highlighting in code blocks. `codeMirrorResources` would be set to `['mode/clojure/clojure']`. * - The `codeMirrorResources` key is an array of CodeMirror resources
* that will be loaded and attached to the CodeMirror module. These
* are made up of addons, keymaps, and modes. For example, for a
* plugin that want's to enable clojure highlighting in code blocks.
* `codeMirrorResources` would be set to `['mode/clojure/clojure']`.
* *
* - The `codeMirrorOptions` key contains all the [CodeMirror](https://codemirror.net/doc/manual.html#config) options that will be set or changed by this plugin. New options can alse be declared via [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption), and then have their value set here. For example, a plugin that enables line numbers would set `codeMirrorOptions` to `{'lineNumbers': true}`. * - The `codeMirrorOptions` key contains all the
* [CodeMirror](https://codemirror.net/doc/manual.html#config)
* options that will be set or changed by this plugin. New options
* can alse be declared via
* [`CodeMirror.defineOption`](https://codemirror.net/doc/manual.html#defineOption),
* and then have their value set here. For example, a plugin that
* enables line numbers would set `codeMirrorOptions` to
* `{'lineNumbers': true}`.
* *
* - Using the **optional** `assets` key you may specify **only** CSS assets that should be loaded in the rendered HTML document. Check for example the Joplin [Mermaid plugin](https://github.com/laurent22/joplin/blob/dev/packages/app-mobile/lib/joplin-renderer/MdToHtml/rules/mermaid.ts) to see how the data should be structured. * - Using the **optional** `assets` key you may specify **only** CSS
* assets that should be loaded in the rendered HTML document. Check
* for example the Joplin [Mermaid
* plugin](https://github.com/laurent22/joplin/blob/dev/packages/renderer/MdToHtml/rules/mermaid.ts)
* to see how the data should be structured.
* *
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys must be provided for the plugin to be valid. Having multiple or all provided is also okay. * One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions`
* keys must be provided for the plugin to be valid. Having multiple or
* all provided is also okay.
* *
* See the [demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script) for an example of all these keys being used in one plugin. * See the [demo
* plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/codemirror_content_script)
* for an example of all these keys being used in one plugin.
*/ */
CodeMirrorPlugin = 'codeMirrorPlugin', CodeMirrorPlugin = 'codeMirrorPlugin',
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "generator-joplin", "name": "generator-joplin",
"version": "1.4.5", "version": "1.5.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -208,12 +208,49 @@ export enum MenuItemLocation {
Note = 'note', Note = 'note',
Tools = 'tools', Tools = 'tools',
Help = 'help', Help = 'help',
/** /**
* @deprecated Do not use - same as NoteListContextMenu * @deprecated Do not use - same as NoteListContextMenu
*/ */
Context = 'context', Context = 'context',
// If adding an item here, don't forget to update isContextMenuItemLocation()
/**
* When a command is called from the note list context menu, the
* command will receive the following arguments:
*
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
*/
NoteListContextMenu = 'noteListContextMenu', NoteListContextMenu = 'noteListContextMenu',
EditorContextMenu = 'editorContextMenu', EditorContextMenu = 'editorContextMenu',
/**
* When a command is called from a folder context menu, the
* command will receive the following arguments:
*
* - `folderId:string`: ID of the folder that was right-clicked on
*/
FolderContextMenu = 'folderContextMenu',
/**
* When a command is called from a tag context menu, the
* command will receive the following arguments:
*
* - `tagId:string`: ID of the tag that was right-clicked on
*/
TagContextMenu = 'tagContextMenu',
}
export function isContextMenuItemLocation(location: MenuItemLocation): boolean {
return [
MenuItemLocation.Context,
MenuItemLocation.NoteListContextMenu,
MenuItemLocation.EditorContextMenu,
MenuItemLocation.FolderContextMenu,
MenuItemLocation.TagContextMenu,
].includes(location);
} }
export interface MenuItem { export interface MenuItem {