Initial scaffold from yo joplin
This commit is contained in:
commit
de18d28146
37 changed files with 5991 additions and 0 deletions
940
api/types.ts
Normal file
940
api/types.ts
Normal file
|
|
@ -0,0 +1,940 @@
|
|||
/* eslint-disable multiline-comment-style */
|
||||
|
||||
// =================================================================
|
||||
// Command API types
|
||||
// =================================================================
|
||||
|
||||
export interface Command {
|
||||
/**
|
||||
* Name of command - must be globally unique
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Label to be displayed on menu items or keyboard shortcut editor for example.
|
||||
* If it is missing, it's assumed it's a private command, to be called programmatically only.
|
||||
* In that case the command will not appear in the shortcut editor or command panel, and logically
|
||||
* should not be used as a menu item.
|
||||
*/
|
||||
label?: string;
|
||||
|
||||
/**
|
||||
* Icon to be used on toolbar buttons for example
|
||||
*/
|
||||
iconName?: string;
|
||||
|
||||
/**
|
||||
* Code to be ran when the command is executed. It may return a result.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
execute(...args: any[]): Promise<any | void>;
|
||||
|
||||
/**
|
||||
* Defines whether the command should be enabled or disabled, which in turns
|
||||
* affects the enabled state of any associated button or menu item.
|
||||
*
|
||||
* The condition should be expressed as a "when-clause" (as in Visual Studio
|
||||
* Code). It's a simple boolean expression that evaluates to `true` or
|
||||
* `false`. It supports the following operators:
|
||||
*
|
||||
* Operator | Symbol | Example
|
||||
* -- | -- | --
|
||||
* Equality | == | "editorType == markdown"
|
||||
* Inequality | != | "currentScreen != config"
|
||||
* Or | \|\| | "noteIsTodo \|\| noteTodoCompleted"
|
||||
* And | && | "oneNoteSelected && !inConflictFolder"
|
||||
*
|
||||
* Joplin, unlike VSCode, also supports parentheses, which allows creating
|
||||
* more complex expressions such as `cond1 || (cond2 && cond3)`. Only one
|
||||
* level of parentheses is possible (nested ones aren't supported).
|
||||
*
|
||||
* Currently the supported context variables aren't documented, but you can
|
||||
* find the list below:
|
||||
*
|
||||
* - [Global When Clauses](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts)
|
||||
* - [Desktop app When Clauses](https://github.com/laurent22/joplin/blob/dev/packages/app-desktop/services/commands/stateToWhenClauseContext.ts)
|
||||
*
|
||||
* Note: Commands are enabled by default unless you use this property.
|
||||
*/
|
||||
enabledCondition?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Interop API types
|
||||
// =================================================================
|
||||
|
||||
export enum FileSystemItem {
|
||||
File = 'file',
|
||||
Directory = 'directory',
|
||||
}
|
||||
|
||||
export enum ImportModuleOutputFormat {
|
||||
Markdown = 'md',
|
||||
Html = 'html',
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to implement a module to export data from Joplin. [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/json_export) for an example.
|
||||
*
|
||||
* In general, all the event handlers you'll need to implement take a `context` object as a first argument. This object will contain the export or import path as well as various optional properties, such as which notes or notebooks need to be exported.
|
||||
*
|
||||
* To get a better sense of what it will contain it can be useful to print it using `console.info(context)`.
|
||||
*/
|
||||
export interface ExportModule {
|
||||
/**
|
||||
* The format to be exported, eg "enex", "jex", "json", etc.
|
||||
*/
|
||||
format: string;
|
||||
|
||||
/**
|
||||
* The description that will appear in the UI, for example in the menu item.
|
||||
*/
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* Whether the module will export a single file or multiple files in a directory. It affects the open dialog that will be presented to the user when using your exporter.
|
||||
*/
|
||||
target: FileSystemItem;
|
||||
|
||||
/**
|
||||
* Only applies to single file exporters or importers
|
||||
* It tells whether the format can package multiple notes into one file.
|
||||
* For example JEX or ENEX can, but HTML cannot.
|
||||
*/
|
||||
isNoteArchive: boolean;
|
||||
|
||||
/**
|
||||
* The extensions of the files exported by your module. For example, it is `["htm", "html"]` for the HTML module, and just `["jex"]` for the JEX module.
|
||||
*/
|
||||
fileExtensions?: string[];
|
||||
|
||||
/**
|
||||
* Called when the export process starts.
|
||||
*/
|
||||
onInit(context: ExportContext): Promise<void>;
|
||||
|
||||
/**
|
||||
* Called when an item needs to be processed. An "item" can be any Joplin object, such as a note, a folder, a notebook, etc.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
onProcessItem(context: ExportContext, itemType: number, item: any): Promise<void>;
|
||||
|
||||
/**
|
||||
* Called when a resource file needs to be exported.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
onProcessResource(context: ExportContext, resource: any, filePath: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Called when the export process is done.
|
||||
*/
|
||||
onClose(context: ExportContext): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ImportModule {
|
||||
/**
|
||||
* The format to be exported, eg "enex", "jex", "json", etc.
|
||||
*/
|
||||
format: string;
|
||||
|
||||
/**
|
||||
* The description that will appear in the UI, for example in the menu item.
|
||||
*/
|
||||
description: string;
|
||||
|
||||
/**
|
||||
* Only applies to single file exporters or importers
|
||||
* It tells whether the format can package multiple notes into one file.
|
||||
* For example JEX or ENEX can, but HTML cannot.
|
||||
*/
|
||||
isNoteArchive: boolean;
|
||||
|
||||
/**
|
||||
* The type of sources that are supported by the module. Tells whether the module can import files or directories or both.
|
||||
*/
|
||||
sources: FileSystemItem[];
|
||||
|
||||
/**
|
||||
* Tells the file extensions of the exported files.
|
||||
*/
|
||||
fileExtensions?: string[];
|
||||
|
||||
/**
|
||||
* Tells the type of notes that will be generated, either HTML or Markdown (default).
|
||||
*/
|
||||
outputFormat?: ImportModuleOutputFormat;
|
||||
|
||||
/**
|
||||
* Called when the import process starts. There is only one event handler within which you should import the complete data.
|
||||
*/
|
||||
onExec(context: ImportContext): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExportOptions {
|
||||
format?: string;
|
||||
path?: string;
|
||||
sourceFolderIds?: string[];
|
||||
sourceNoteIds?: string[];
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
}
|
||||
|
||||
export interface ExportContext {
|
||||
destPath: string;
|
||||
options: ExportOptions;
|
||||
|
||||
/**
|
||||
* You can attach your own custom data using this property - it will then be passed to each event handler, allowing you to keep state from one event to the next.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
userData?: any;
|
||||
}
|
||||
|
||||
export interface ImportContext {
|
||||
sourcePath: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
options: any;
|
||||
warnings: string[];
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Misc types
|
||||
// =================================================================
|
||||
|
||||
export interface Script {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
onStart?(event: any): Promise<void>;
|
||||
}
|
||||
|
||||
export interface Disposable {
|
||||
// dispose():void;
|
||||
}
|
||||
|
||||
export enum ModelType {
|
||||
Note = 1,
|
||||
Folder = 2,
|
||||
Setting = 3,
|
||||
Resource = 4,
|
||||
Tag = 5,
|
||||
NoteTag = 6,
|
||||
Search = 7,
|
||||
Alarm = 8,
|
||||
MasterKey = 9,
|
||||
ItemChange = 10,
|
||||
NoteResource = 11,
|
||||
ResourceLocalState = 12,
|
||||
Revision = 13,
|
||||
Migration = 14,
|
||||
SmartFilter = 15,
|
||||
Command = 16,
|
||||
}
|
||||
|
||||
export interface VersionInfo {
|
||||
version: string;
|
||||
profileVersion: number;
|
||||
syncVersion: number;
|
||||
|
||||
platform: 'desktop'|'mobile';
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Menu types
|
||||
// =================================================================
|
||||
|
||||
export interface CreateMenuItemOptions {
|
||||
accelerator: string;
|
||||
}
|
||||
|
||||
export enum MenuItemLocation {
|
||||
File = 'file',
|
||||
Edit = 'edit',
|
||||
View = 'view',
|
||||
Note = 'note',
|
||||
Tools = 'tools',
|
||||
Help = 'help',
|
||||
|
||||
/**
|
||||
* @deprecated Do not use - same as NoteListContextMenu
|
||||
*/
|
||||
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',
|
||||
|
||||
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 {
|
||||
/**
|
||||
* Command that should be associated with the menu item. All menu item should
|
||||
* have a command associated with them unless they are a sub-menu.
|
||||
*/
|
||||
commandName?: string;
|
||||
|
||||
/**
|
||||
* Arguments that should be passed to the command. They will be as rest
|
||||
* parameters.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
commandArgs?: any[];
|
||||
|
||||
/**
|
||||
* Set to "separator" to create a divider line
|
||||
*/
|
||||
type?: ('normal' | 'separator' | 'submenu' | 'checkbox' | 'radio');
|
||||
|
||||
/**
|
||||
* Accelerator associated with the menu item
|
||||
*/
|
||||
accelerator?: string;
|
||||
|
||||
/**
|
||||
* Menu items that should appear below this menu item. Allows creating a menu tree.
|
||||
*/
|
||||
submenu?: MenuItem[];
|
||||
|
||||
/**
|
||||
* Menu item label. If not specified, the command label will be used instead.
|
||||
*/
|
||||
label?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// View API types
|
||||
// =================================================================
|
||||
|
||||
export interface ButtonSpec {
|
||||
id: ButtonId;
|
||||
title?: string;
|
||||
onClick?(): void;
|
||||
}
|
||||
|
||||
export type ButtonId = string;
|
||||
|
||||
export enum ToolbarButtonLocation {
|
||||
/**
|
||||
* This toolbar in the top right corner of the application. It applies to the note as a whole, including its metadata.
|
||||
*
|
||||
* <span class="platform-desktop">desktop</span>
|
||||
*/
|
||||
NoteToolbar = 'noteToolbar',
|
||||
|
||||
/**
|
||||
* This toolbar is right above the text editor. It applies to the note body only.
|
||||
*/
|
||||
EditorToolbar = 'editorToolbar',
|
||||
}
|
||||
|
||||
export type ViewHandle = string;
|
||||
|
||||
export interface EditorCommand {
|
||||
name: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
value?: any;
|
||||
}
|
||||
|
||||
export interface DialogResult {
|
||||
id: ButtonId;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
formData?: any;
|
||||
}
|
||||
|
||||
export enum ToastType {
|
||||
Info = 'info',
|
||||
Success = 'success',
|
||||
Error = 'error',
|
||||
}
|
||||
|
||||
export interface Toast {
|
||||
message: string;
|
||||
type?: ToastType;
|
||||
duration?: number;
|
||||
timestamp?: number;
|
||||
}
|
||||
|
||||
export interface Size {
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export interface Rectangle {
|
||||
x?: number;
|
||||
y?: number;
|
||||
width?: number;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export interface EditorUpdateEvent {
|
||||
newBody: string;
|
||||
noteId: string;
|
||||
}
|
||||
export type UpdateCallback = (event: EditorUpdateEvent)=> Promise<void>;
|
||||
|
||||
|
||||
export interface ActivationCheckEvent {
|
||||
handle: ViewHandle;
|
||||
noteId: string;
|
||||
}
|
||||
export type ActivationCheckCallback = (event: ActivationCheckEvent)=> Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Required callbacks for creating an editor plugin.
|
||||
*/
|
||||
export interface EditorPluginCallbacks {
|
||||
/**
|
||||
* Emitted when the editor can potentially be activated - this is for example when the current
|
||||
* note is changed, or when the application is opened. At that point you should check the
|
||||
* current note and decide whether your editor should be activated or not. If it should, return
|
||||
* `true`, otherwise return `false`.
|
||||
*/
|
||||
onActivationCheck: ActivationCheckCallback;
|
||||
|
||||
/**
|
||||
* Emitted when an editor view is created. This happens, for example, when a new window containing
|
||||
* a new editor is created.
|
||||
*
|
||||
* This callback should set the editor plugin's HTML using `editors.setHtml`, add scripts to the editor
|
||||
* with `editors.addScript`, and optionally listen for external changes using `editors.onUpdate`.
|
||||
*/
|
||||
onSetup: (handle: ViewHandle)=> Promise<void>;
|
||||
}
|
||||
|
||||
export type VisibleHandler = ()=> Promise<void>;
|
||||
|
||||
export interface EditContextMenuFilterObject {
|
||||
items: MenuItem[];
|
||||
}
|
||||
|
||||
export interface EditorActivationCheckFilterObject {
|
||||
effectiveNoteId: string;
|
||||
windowId: string;
|
||||
activatedEditors: {
|
||||
pluginId: string;
|
||||
viewId: string;
|
||||
isActive: boolean;
|
||||
}[];
|
||||
}
|
||||
|
||||
export type FilterHandler<T> = (object: T)=> Promise<T>;
|
||||
|
||||
export type CommandArgument = string|number|object|boolean|null;
|
||||
|
||||
export interface MenuTemplateItem {
|
||||
label?: string;
|
||||
command?: string;
|
||||
commandArgs?: CommandArgument[];
|
||||
}
|
||||
|
||||
export interface WebviewApi {
|
||||
postMessage: (message: object)=> unknown;
|
||||
onMessage: (message: object)=> void;
|
||||
menuPopupFromTemplate: (template: MenuTemplateItem[])=> void;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Settings types
|
||||
// =================================================================
|
||||
|
||||
export enum SettingItemType {
|
||||
Int = 1,
|
||||
String = 2,
|
||||
Bool = 3,
|
||||
Array = 4,
|
||||
Object = 5,
|
||||
Button = 6,
|
||||
}
|
||||
|
||||
export enum SettingItemSubType {
|
||||
FilePathAndArgs = 'file_path_and_args',
|
||||
FilePath = 'file_path', // Not supported on mobile!
|
||||
DirectoryPath = 'directory_path', // Not supported on mobile!
|
||||
}
|
||||
|
||||
export enum AppType {
|
||||
Desktop = 'desktop',
|
||||
Mobile = 'mobile',
|
||||
Cli = 'cli',
|
||||
}
|
||||
|
||||
export enum SettingStorage {
|
||||
Database = 1,
|
||||
File = 2,
|
||||
}
|
||||
|
||||
// Redefine a simplified interface to mask internal details
|
||||
// and to remove function calls as they would have to be async.
|
||||
export interface SettingItem {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
value: any;
|
||||
type: SettingItemType;
|
||||
|
||||
/**
|
||||
* Currently only used to display a file or directory selector. Always set
|
||||
* `type` to `SettingItemType.String` when using this property.
|
||||
*/
|
||||
subType?: SettingItemSubType;
|
||||
|
||||
label: string;
|
||||
description?: string;
|
||||
|
||||
/**
|
||||
* A public setting will appear in the Configuration screen and will be
|
||||
* modifiable by the user. A private setting however will not appear there,
|
||||
* and can only be changed programmatically. You may use this to store some
|
||||
* values that you do not want to directly expose.
|
||||
*/
|
||||
public: boolean;
|
||||
|
||||
/**
|
||||
* You would usually set this to a section you would have created
|
||||
* specifically for the plugin.
|
||||
*/
|
||||
section?: string;
|
||||
|
||||
/**
|
||||
* To create a setting with multiple options, set this property to `true`.
|
||||
* That setting will render as a dropdown list in the configuration screen.
|
||||
*/
|
||||
isEnum?: boolean;
|
||||
|
||||
/**
|
||||
* This property is required when `isEnum` is `true`. In which case, it
|
||||
* should contain a map of value => label.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
options?: Record<any, any>;
|
||||
|
||||
/**
|
||||
* Reserved property. Not used at the moment.
|
||||
*/
|
||||
appTypes?: AppType[];
|
||||
|
||||
/**
|
||||
* Set this to `true` to store secure data, such as passwords. Any such
|
||||
* setting will be stored in the system keychain if one is available.
|
||||
*/
|
||||
secure?: boolean;
|
||||
|
||||
/**
|
||||
* An advanced setting will be moved under the "Advanced" button in the
|
||||
* config screen.
|
||||
*/
|
||||
advanced?: boolean;
|
||||
|
||||
/**
|
||||
* Set the min, max and step values if you want to restrict an int setting
|
||||
* to a particular range.
|
||||
*/
|
||||
minimum?: number;
|
||||
maximum?: number;
|
||||
step?: number;
|
||||
|
||||
/**
|
||||
* Either store the setting in the database or in settings.json. Defaults to database.
|
||||
*/
|
||||
storage?: SettingStorage;
|
||||
}
|
||||
|
||||
export interface SettingSection {
|
||||
label: string;
|
||||
iconName?: string;
|
||||
description?: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Data API types
|
||||
// =================================================================
|
||||
|
||||
/**
|
||||
* An array of at least one element and at most three elements.
|
||||
*
|
||||
* - **[0]**: Resource name (eg. "notes", "folders", "tags", etc.)
|
||||
* - **[1]**: (Optional) Resource ID.
|
||||
* - **[2]**: (Optional) Resource link.
|
||||
*/
|
||||
export type Path = string[];
|
||||
|
||||
// =================================================================
|
||||
// Clipboard API types
|
||||
// =================================================================
|
||||
|
||||
/**
|
||||
* Represents content that can be written to the clipboard in multiple formats.
|
||||
*/
|
||||
export interface ClipboardContent {
|
||||
/**
|
||||
* Plain text representation of the content
|
||||
*/
|
||||
text?: string;
|
||||
|
||||
/**
|
||||
* HTML representation of the content
|
||||
*/
|
||||
html?: string;
|
||||
|
||||
/**
|
||||
* Image in [data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) format
|
||||
*/
|
||||
image?: string;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Content Script types
|
||||
// =================================================================
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
export type PostMessageHandler = (message: any)=> Promise<any>;
|
||||
|
||||
/**
|
||||
* When a content script is initialised, it receives a `context` object.
|
||||
*/
|
||||
export interface ContentScriptContext {
|
||||
/**
|
||||
* The plugin ID that registered this content script
|
||||
*/
|
||||
pluginId: string;
|
||||
|
||||
/**
|
||||
* The content script ID, which may be necessary to post messages
|
||||
*/
|
||||
contentScriptId: string;
|
||||
|
||||
/**
|
||||
* Can be used by CodeMirror content scripts to post a message to the plugin
|
||||
*/
|
||||
postMessage: PostMessageHandler;
|
||||
}
|
||||
|
||||
export interface ContentScriptModuleLoadedEvent {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
userData?: any;
|
||||
}
|
||||
|
||||
export interface ContentScriptModule {
|
||||
onLoaded?: (event: ContentScriptModuleLoadedEvent)=> void;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
plugin: ()=> any;
|
||||
assets?: ()=> void;
|
||||
}
|
||||
|
||||
export interface MarkdownItContentScriptModule extends Omit<ContentScriptModule, 'plugin'> {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
plugin: (markdownIt: any, options: any)=> any;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
type EditorCommandCallback = (...args: any[])=> any;
|
||||
|
||||
export interface CodeMirrorControl {
|
||||
/** Points to a CodeMirror 6 EditorView instance. */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
editor: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
cm6: any;
|
||||
|
||||
/** `extension` should be a [CodeMirror 6 extension](https://codemirror.net/docs/ref/#state.Extension). */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
addExtension(extension: any|any[]): void;
|
||||
|
||||
supportsCommand(name: string): boolean;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
execCommand(name: string, ...args: any[]): any;
|
||||
registerCommand(name: string, callback: EditorCommandCallback): void;
|
||||
|
||||
joplinExtensions: {
|
||||
/**
|
||||
* Returns a [CodeMirror 6 extension](https://codemirror.net/docs/ref/#state.Extension) that
|
||||
* registers the given [CompletionSource](https://codemirror.net/docs/ref/#autocomplete.CompletionSource).
|
||||
*
|
||||
* Use this extension rather than the built-in CodeMirror [`autocompletion`](https://codemirror.net/docs/ref/#autocomplete.autocompletion)
|
||||
* if you don't want to use [languageData-based autocompletion](https://codemirror.net/docs/ref/#autocomplete.autocompletion^config.override).
|
||||
*
|
||||
* Using `autocompletion({ override: [ ... ]})` causes errors when done by multiple plugins.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
completionSource(completionSource: any): any;
|
||||
|
||||
/**
|
||||
* Creates an extension that enables or disables [`languageData`-based autocompletion](https://codemirror.net/docs/ref/#autocomplete.autocompletion^config.override).
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
enableLanguageDataAutocomplete: { of: (enabled: boolean)=> any };
|
||||
|
||||
/**
|
||||
* A CodeMirror [facet](https://codemirror.net/docs/ref/#state.EditorState.facet) that contains
|
||||
* the ID of the note currently open in the editor.
|
||||
*
|
||||
* Access the value of this facet using
|
||||
* ```ts
|
||||
* const noteIdFacet = editorControl.joplinExtensions.noteIdFacet;
|
||||
* const editorState = editorControl.editor.state;
|
||||
* const noteId = editorState.facet(noteIdFacet);
|
||||
* ```
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- No better type available
|
||||
noteIdFacet: any;
|
||||
/**
|
||||
* A CodeMirror [StateEffect](https://codemirror.net/docs/ref/#state.StateEffect) that is
|
||||
* included in a [Transaction](https://codemirror.net/docs/ref/#state.Transaction) when the
|
||||
* note ID changes.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- No better type available
|
||||
setNoteIdEffect: any;
|
||||
};
|
||||
}
|
||||
|
||||
export interface MarkdownEditorContentScriptModule extends Omit<ContentScriptModule, 'plugin'> {
|
||||
plugin: (editorControl: CodeMirrorControl)=> void;
|
||||
}
|
||||
|
||||
export enum ContentScriptType {
|
||||
/**
|
||||
* Registers a new Markdown-It plugin, which should follow the template
|
||||
* below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(markdownIt, pluginOptions) {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* ## Exported members
|
||||
*
|
||||
* - The `context` argument is currently unused but could be used later on
|
||||
* to provide access to your own plugin so that the content script and
|
||||
* plugin can communicate.
|
||||
*
|
||||
* - The **required** `plugin` key is the actual Markdown-It plugin - check
|
||||
* the [official doc](https://github.com/markdown-it/markdown-it) for more
|
||||
* information.
|
||||
*
|
||||
* - 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.
|
||||
*
|
||||
* ## Supporting the Rich Text Editor
|
||||
*
|
||||
* Joplin's Rich Text Editor works with rendered HTML, which is converted back
|
||||
* to markdown when saving. To prevent the original markdown for your plugin from
|
||||
* being lost, Joplin needs additional metadata.
|
||||
*
|
||||
* To provide this,
|
||||
* 1. Wrap the HTML generated by your plugin in an element with class `joplin-editable`.
|
||||
* For example,
|
||||
* ```html
|
||||
* <div class="joplin-editable">
|
||||
* ...your html...
|
||||
* </div>
|
||||
* ```
|
||||
* 2. Add a child with class `joplin-source` that contains the original markdown that
|
||||
* was rendered by your plugin. Include `data-joplin-source-open`, `data-joplin-source-close`,
|
||||
* and `data-joplin-language` attributes.
|
||||
* For example, if your plugin rendered the following code block,
|
||||
* ````
|
||||
* ```foo
|
||||
* ... original source here ...
|
||||
* ```
|
||||
* ````
|
||||
* then it should render to
|
||||
* ```html
|
||||
* <div class="joplin-editable">
|
||||
* <pre
|
||||
* class="joplin-source"
|
||||
* data-joplin-language="foo"
|
||||
* data-joplin-source-open="```foo
"
|
||||
* data-joplin-source-close="```"
|
||||
* > ... original source here ... </pre>
|
||||
* ... rendered HTML here ...
|
||||
* </div>
|
||||
* ```
|
||||
*
|
||||
* See [the demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/content_script)
|
||||
* for a complete example.
|
||||
*
|
||||
* ## Getting the settings from the renderer
|
||||
*
|
||||
* You can access your plugin settings from the renderer by calling
|
||||
* `pluginOptions.settingValue("your-setting-key')`.
|
||||
*
|
||||
* ## Posting messages from the content script to your plugin
|
||||
*
|
||||
* The application provides the following function to allow executing
|
||||
* commands from the rendered HTML code:
|
||||
*
|
||||
* ```javascript
|
||||
* const response = await webviewApi.postMessage(contentScriptId, message);
|
||||
* ```
|
||||
*
|
||||
* - `contentScriptId` is the ID you've defined when you registered the
|
||||
* content script. You can retrieve it from the
|
||||
* {@link ContentScriptContext | context}.
|
||||
* - `message` can be any basic JavaScript type (number, string, plain
|
||||
* object), but it cannot be a function or class instance.
|
||||
*
|
||||
* When you post a message, the plugin can send back a `response` thus
|
||||
* allowing two-way communication:
|
||||
*
|
||||
* ```javascript
|
||||
* await joplin.contentScripts.onMessage(contentScriptId, (message) => {
|
||||
* // Process message
|
||||
* return response; // Can be any object, string or number
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* See {@link JoplinContentScripts.onMessage} for more details, as well as
|
||||
* the [postMessage
|
||||
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/post_messages).
|
||||
*
|
||||
* ## 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
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: require('markdown-it-toc-done-right');
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
MarkdownItPlugin = 'markdownItPlugin',
|
||||
|
||||
/**
|
||||
* Registers a new CodeMirror plugin, which should follow the template
|
||||
* below.
|
||||
*
|
||||
* ```javascript
|
||||
* module.exports = {
|
||||
* default: function(context) {
|
||||
* return {
|
||||
* plugin: function(CodeMirror) {
|
||||
* // ...
|
||||
* },
|
||||
* codeMirrorResources: [],
|
||||
* codeMirrorOptions: {
|
||||
* // ...
|
||||
* },
|
||||
* assets: {
|
||||
* // ...
|
||||
* },
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* - The `context` argument allows communicating with other parts of
|
||||
* your plugin (see below).
|
||||
*
|
||||
* - 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.
|
||||
*
|
||||
* - **CodeMirror 5 only**: 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']`.
|
||||
* This field is ignored on mobile and when the desktop beta editor is enabled.
|
||||
*
|
||||
* - **CodeMirror 5 only**: 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/renderer/MdToHtml/rules/mermaid.ts)
|
||||
* to see how the data should be structured.
|
||||
*
|
||||
* One of the `plugin`, `codeMirrorResources`, or `codeMirrorOptions` keys
|
||||
* must be provided for the plugin to be valid. Having multiple or all
|
||||
* provided is also okay.
|
||||
*
|
||||
* See also:
|
||||
* - 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 editor plugin tutorial](https://joplinapp.org/help/api/tutorials/cm6_plugin)
|
||||
* for how to develop a plugin for the mobile editor and the desktop beta markdown editor.
|
||||
*
|
||||
* ## Posting messages from the content script to your plugin
|
||||
*
|
||||
* In order to post messages to the plugin, you can use the postMessage
|
||||
* function passed to the {@link ContentScriptContext | context}.
|
||||
*
|
||||
* ```javascript
|
||||
* const response = await context.postMessage('messageFromCodeMirrorContentScript');
|
||||
* ```
|
||||
*
|
||||
* When you post a message, the plugin can send back a `response` thus
|
||||
* allowing two-way communication:
|
||||
*
|
||||
* ```javascript
|
||||
* await joplin.contentScripts.onMessage(contentScriptId, (message) => {
|
||||
* // Process message
|
||||
* return response; // Can be any object, string or number
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* See {@link JoplinContentScripts.onMessage} for more details, as well as
|
||||
* the [postMessage
|
||||
* demo](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins/post_messages).
|
||||
*
|
||||
*/
|
||||
CodeMirrorPlugin = 'codeMirrorPlugin',
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue