Files
logseq/libs/src/LSPlugin.ts
Charlie 79bc33e1e3 Enhance/more ns plugin api (#4828)
* improve(plugin): WIP add settings schema

* improve(plugin): add identity for settings modal

* improve(plugin): WIP add settings input

* fix(ui): scrollbar overlay of modal panel content

* improve(plugin): WIP add more render types of setting item

* improve(plugin): WIP polish settings items

* improve(plugin): WIP settings list of plugins

* improve(plugin): more settings types & polish releated ui

* fix(plugin): sometimes disable plugin not work

* improve(plugin): polish ui of plugin settings

* fix(dev): warning of lint

* improve(plugin): add api of settings changed

* chore: build libs core

* fix(ui): width of settings panel wrap

* improve(plugin): separate layouts data from settings aio file

* imporve(plugin): container size of single plugin settings

* fix: add missing state

* improve(plugin): add Git ns

* improve(plugin): git related api

* improve(api): type of git result

* chore: build libs core

* fix(dev): kondo lint

* fix(plugin): use cdn sdk when js entry

* chore: build libs core

* fix(plugin): env condition

* improve(plugin): add UI ns

* fix(api): arguments of datascript query

* enhance(api): manageable message instance of UI tools

* enhance(api): WIP add experiments api

* enhance(api): WIP add resources state of plugin

* improve(plugin): add status of loading script resources

* improve(plugin): more opts for script loader

* improve(plugin): WIP add fenced code renderer hook

* improve(plugin): fenced code renderer hook

* fix(plugin): resource root path of plugin fs location

* imporve(plugin): support local files for loading scripts

* improve(plugin): types of expirements api

* fix: typo of class

* enhance(api): add namespace related apis

* enhance(api): add linked refrences related apis

* enhance(plugin): add sample links to related api comments

* improve(plugin): add db changed hook & optimize strategy of caller for hooks

* improve(plugin): compatible commands registration for old sdk

* improve(plugin): collect user sdk version for plugin local

* improve(plugin): add internal callable apis for user sdk

* chore(plugin): missing files & bump libs version

* improve(plugin): compatiable for old sdk about hook messaging optimization

* improve(plugin): db hook optimization for old sdk

* enhance(ux): auto focus searchbar when open plugins list

* improve(plugin): api of a hook from specific block changed event

* improve(plugin): api of db block change hook

* improve(plugin): add show bracket user config of api

* improve(plugin): api of db block change hook

* fix(api): toggle collapsed of block

* improve(api): try to init grpah with git before exec git commands

* improve(plugin): attributes of sandbox container

* improve(dev): support register command with keybinding

* improve(plugin): add api of register shortcut command

* fix(plugin): reubild slash commands when new command registration

* fix(dev): lint

* improve(dev): lint script of libs codebase

* chore(dev): remove useless codes

* improve(plugin):sanitize path string of plugin repo value

* fix(plugin): rebuild commands list when unregister a plugin

* fix(ui): overflow width of query result table

* chore: rebuild libs core

* improve(plugin): add assets related apis

* chore: rebuild libs core

* improve(plugin): support replace state of into block in page api

* improve(plugin): prepend/append child block in page

* improve(plugin): polished exceptions message of plugin update/install

* fix(plugin): update settings within gui

* improve(ux): debounce change event of input for plugin settings gui

* chore: rebuild libs core

* enhance(plugin): catch exception of hook plugin
2022-04-21 18:43:16 +08:00

883 lines
21 KiB
TypeScript

import EventEmitter from 'eventemitter3'
import * as CSS from 'csstype'
import { LSPluginCaller } from './LSPlugin.caller'
import { LSPluginFileStorage } from './modules/LSPlugin.Storage'
import { LSPluginExperiments } from './modules/LSPlugin.Experiments'
export type PluginLocalIdentity = string
export type ThemeOptions = {
name: string
url: string
description?: string
mode?: 'dark' | 'light'
[key: string]: any
}
export type StyleString = string
export type StyleOptions = {
key?: string
style: StyleString
}
export type UIContainerAttrs = {
draggable: boolean
resizable: boolean
[key: string]: any
}
export type UIBaseOptions = {
key?: string
replace?: boolean
template: string | null
style?: CSS.Properties
attrs?: Record<string, string>
close?: 'outside' | string
reset?: boolean // reset slot content or not
}
export type UIPathIdentity = {
/**
* DOM selector
*/
path: string
}
export type UISlotIdentity = {
/**
* Slot key
*/
slot: string
}
export type UISlotOptions = UIBaseOptions & UISlotIdentity
export type UIPathOptions = UIBaseOptions & UIPathIdentity
export type UIOptions = UIBaseOptions | UIPathOptions | UISlotOptions
export interface LSPluginPkgConfig {
id: PluginLocalIdentity
main: string
entry: string // alias of main
title: string
mode: 'shadow' | 'iframe'
themes: Array<ThemeOptions>
icon: string
[key: string]: any
}
export interface LSPluginBaseInfo {
id: string // should be unique
mode: 'shadow' | 'iframe'
settings: {
disabled: boolean
[key: string]: any
}
[key: string]: any
}
export type IHookEvent = {
[key: string]: any
}
export type IUserOffHook = () => void
export type IUserHook<E = any, R = IUserOffHook> = (
callback: (e: IHookEvent & E) => void
) => IUserOffHook
export type IUserSlotHook<E = any> = (
callback: (e: IHookEvent & UISlotIdentity & E) => void
) => void
export type EntityID = number
export type BlockUUID = string
export type BlockUUIDTuple = ['uuid', BlockUUID]
export type IEntityID = { id: EntityID; [key: string]: any }
export type IBatchBlock = {
content: string
properties?: Record<string, any>
children?: Array<IBatchBlock>
}
export type IDatom = [e: number, a: string, v: any, t: number, added: boolean]
export type IGitResult = { stdout: string; stderr: string; exitCode: number }
export interface AppUserInfo {
[key: string]: any
}
/**
* User's app configurations
*/
export interface AppUserConfigs {
preferredThemeMode: 'dark' | 'light'
preferredFormat: 'markdown' | 'org'
preferredDateFormat: string
preferredStartOfWeek: string
preferredLanguage: string
preferredWorkflow: string
currentGraph: string
showBracket: boolean
[key: string]: any
}
/**
* In Logseq, a graph represents a repository of connected pages and blocks
*/
export interface AppGraphInfo {
name: string
url: string
path: string
[key: string]: any
}
/**
* Block - Logseq's fundamental data structure.
*/
export interface BlockEntity {
id: EntityID // db id
uuid: BlockUUID
left: IEntityID
format: 'markdown' | 'org'
parent: IEntityID
unordered: boolean
content: string
page: IEntityID
// optional fields in dummy page
anchor?: string
body?: any
children?: Array<BlockEntity | BlockUUIDTuple>
container?: string
file?: IEntityID
level?: number
meta?: { timestamps: any; properties: any; startPos: number; endPos: number }
title?: Array<any>
[key: string]: any
}
/**
* Page is just a block with some specific properties.
*/
export interface PageEntity {
id: EntityID
uuid: BlockUUID
name: string
originalName: string
'journal?': boolean
file?: IEntityID
namespace?: IEntityID
children?: Array<PageEntity>
format?: 'markdown' | 'org'
journalDay?: number
}
export type BlockIdentity = BlockUUID | Pick<BlockEntity, 'uuid'>
export type BlockPageName = string
export type PageIdentity = BlockPageName | BlockIdentity
export type SlashCommandActionCmd =
| 'editor/input'
| 'editor/hook'
| 'editor/clear-current-slash'
| 'editor/restore-saved-cursor'
export type SlashCommandAction = [cmd: SlashCommandActionCmd, ...args: any]
export type SimpleCommandCallback = (e: IHookEvent) => void
export type BlockCommandCallback = (
e: IHookEvent & { uuid: BlockUUID }
) => Promise<void>
export type BlockCursorPosition = {
left: number
top: number
height: number
pos: number
rect: DOMRect
}
export type SimpleCommandKeybinding = {
mode?: 'global' | 'non-editing' | 'editing'
binding: string
mac?: string // special for Mac OS
}
export type SettingSchemaDesc = {
key: string
type: 'string' | 'number' | 'boolean' | 'enum' | 'object'
default: string | number | boolean | Array<any> | object | null
title: string
description: string // support markdown
inputAs?: 'color' | 'date' | 'datetime-local' | 'range'
enumChoices?: Array<string>
enumPicker?: 'select' | 'radio' | 'checkbox' // default: select
}
export type ExternalCommandType =
| 'logseq.command/run'
| 'logseq.editor/cycle-todo'
| 'logseq.editor/down'
| 'logseq.editor/up'
| 'logseq.editor/expand-block-children'
| 'logseq.editor/collapse-block-children'
| 'logseq.editor/open-file-in-default-app'
| 'logseq.editor/open-file-in-directory'
| 'logseq.editor/select-all-blocks'
| 'logseq.editor/toggle-open-blocks'
| 'logseq.editor/zoom-in'
| 'logseq.editor/zoom-out'
| 'logseq.editor/indent'
| 'logseq.editor/outdent'
| 'logseq.editor/copy'
| 'logseq.editor/cut'
| 'logseq.go/home'
| 'logseq.go/journals'
| 'logseq.go/keyboard-shortcuts'
| 'logseq.go/next-journal'
| 'logseq.go/prev-journal'
| 'logseq.go/search'
| 'logseq.go/search-in-page'
| 'logseq.go/tomorrow'
| 'logseq.go/backward'
| 'logseq.go/forward'
| 'logseq.search/re-index'
| 'logseq.sidebar/clear'
| 'logseq.sidebar/open-today-page'
| 'logseq.ui/goto-plugins'
| 'logseq.ui/select-theme-color'
| 'logseq.ui/toggle-brackets'
| 'logseq.ui/toggle-cards'
| 'logseq.ui/toggle-contents'
| 'logseq.ui/toggle-document-mode'
| 'logseq.ui/toggle-help'
| 'logseq.ui/toggle-left-sidebar'
| 'logseq.ui/toggle-right-sidebar'
| 'logseq.ui/toggle-settings'
| 'logseq.ui/toggle-theme'
| 'logseq.ui/toggle-wide-mode'
| 'logseq.command-palette/toggle'
export type UserProxyTags = 'app' | 'editor' | 'db' | 'git' | 'ui' | 'assets'
/**
* App level APIs
*/
export interface IAppProxy {
// base
getUserInfo: () => Promise<AppUserInfo | null>
getUserConfigs: () => Promise<AppUserConfigs>
// commands
registerCommand: (
type: string,
opts: {
key: string
label: string
desc?: string
palette?: boolean
keybinding?: SimpleCommandKeybinding
},
action: SimpleCommandCallback
) => void
registerCommandPalette: (
opts: {
key: string
label: string
keybinding?: SimpleCommandKeybinding
},
action: SimpleCommandCallback
) => void
registerCommandShortcut: (
keybinding: SimpleCommandKeybinding,
action: SimpleCommandCallback
) => void
invokeExternalCommand: (
type: ExternalCommandType,
...args: Array<any>
) => Promise<void>
/**
* Get state from app store
* valid state is here
* https://github.com/logseq/logseq/blob/master/src/main/frontend/state.cljs#L27
*
* @example
* ```ts
* const isDocMode = await logseq.App.getStateFromStore('document/mode?')
* ```
* @param path
*/
getStateFromStore: <T = any>(path: string | Array<string>) => Promise<T>
// native
relaunch: () => Promise<void>
quit: () => Promise<void>
openExternalLink: (url: string) => Promise<void>
/**
* @deprecated Using `logseq.Git.execCommand`
* @link https://github.com/desktop/dugite/blob/master/docs/api/exec.md
* @param args
*/
execGitCommand: (args: string[]) => Promise<string>
// graph
getCurrentGraph: () => Promise<AppGraphInfo | null>
// router
pushState: (
k: string,
params?: Record<string, any>,
query?: Record<string, any>
) => void
replaceState: (
k: string,
params?: Record<string, any>,
query?: Record<string, any>
) => void
// ui
queryElementById: (id: string) => Promise<string | boolean>
showMsg: (
content: string,
status?: 'success' | 'warning' | 'error' | string
) => void
setZoomFactor: (factor: number) => void
setFullScreen: (flag: boolean | 'toggle') => void
setLeftSidebarVisible: (flag: boolean | 'toggle') => void
setRightSidebarVisible: (flag: boolean | 'toggle') => void
registerUIItem: (
type: 'toolbar' | 'pagebar',
opts: { key: string; template: string }
) => void
registerPageMenuItem: (
tag: string,
action: (e: IHookEvent & { page: string }) => void
) => void
// hook events
onCurrentGraphChanged: IUserHook
onThemeModeChanged: IUserHook<{ mode: 'dark' | 'light' }>
onBlockRendererSlotted: IUserSlotHook<{ uuid: BlockUUID }>
/**
* provide ui slot to block `renderer` macro for `{{renderer arg1, arg2}}`
*
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-pomodoro-timer
* @example
* ```ts
* // e.g. {{renderer :h1, hello world, green}}
*
* logseq.App.onMacroRendererSlotted(({ slot, payload: { arguments } }) => {
* let [type, text, color] = arguments
* if (type !== ':h1') return
* logseq.provideUI({
* key: 'h1-playground',
* slot, template: `
* <h2 style="color: ${color || 'red'}">${text}</h2>
* `,
* })
* })
* ```
*/
onMacroRendererSlotted: IUserSlotHook<{
payload: { arguments: Array<string>; uuid: string; [key: string]: any }
}>
onPageHeadActionsSlotted: IUserSlotHook
onRouteChanged: IUserHook<{ path: string; template: string }>
onSidebarVisibleChanged: IUserHook<{ visible: boolean }>
// internal
_installPluginHook: (pid: string, hook: string) => void
_uninstallPluginHook: (pid: string, hookOrAll: string | boolean) => void
}
/**
* Editor related APIs
*/
export interface IEditorProxy extends Record<string, any> {
/**
* register a custom command which will be added to the Logseq slash command list
* @param tag - displayed name of command
* @param action - can be a single callback function to run when the command is called, or an array of fixed commands with arguments
*
*
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-slash-commands
*
* @example
* ```ts
* logseq.Editor.registerSlashCommand("Say Hi", () => {
* console.log('Hi!')
* })
* ```
*
* @example
* ```ts
* logseq.Editor.registerSlashCommand("💥 Big Bang", [
* ["editor/hook", "customCallback"],
* ["editor/clear-current-slash"],
* ]);
* ```
*/
registerSlashCommand: (
tag: string,
action: BlockCommandCallback | Array<SlashCommandAction>
) => unknown
/**
* register a custom command in the block context menu (triggered by right clicking the block dot)
* @param tag - displayed name of command
* @param action - can be a single callback function to run when the command is called
*/
registerBlockContextMenuItem: (
tag: string,
action: BlockCommandCallback
) => unknown
// block related APIs
checkEditing: () => Promise<BlockUUID | boolean>
insertAtEditingCursor: (content: string) => Promise<void>
restoreEditingCursor: () => Promise<void>
exitEditingMode: (selectBlock?: boolean) => Promise<void>
getEditingCursorPosition: () => Promise<BlockCursorPosition | null>
getEditingBlockContent: () => Promise<string>
getCurrentPage: () => Promise<PageEntity | BlockEntity | null>
getCurrentBlock: () => Promise<BlockEntity | null>
getSelectedBlocks: () => Promise<Array<BlockEntity> | null>
/**
* get all blocks of the current page as a tree structure
*
* @example
* ```ts
* const blocks = await logseq.Editor.getCurrentPageBlocksTree()
* initMindMap(blocks)
* ```
*/
getCurrentPageBlocksTree: () => Promise<Array<BlockEntity>>
/**
* get all blocks for the specified page
*
* @param srcPage - the page name or uuid
*/
getPageBlocksTree: (srcPage: PageIdentity) => Promise<Array<BlockEntity>>
/**
* get all page/block linked references
* @param srcPage
*/
getPageLinkedReferences: (
srcPage: PageIdentity
) => Promise<Array<[page: PageEntity, blocks: Array<BlockEntity>]> | null>
/**
* get flatten pages from top namespace
* @param namespace
*/
getPagesFromNamespace: (
namespace: BlockPageName
) => Promise<Array<PageEntity> | null>
/**
* construct pages tree from namespace pages
* @param namespace
*/
getPagesTreeFromNamespace: (
namespace: BlockPageName
) => Promise<Array<PageEntity> | null>
/**
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-reddit-hot-news
*
* @param srcBlock
* @param content
* @param opts
*/
insertBlock: (
srcBlock: BlockIdentity,
content: string,
opts?: Partial<{
before: boolean
sibling: boolean
isPageBlock: boolean
properties: {}
}>
) => Promise<BlockEntity | null>
insertBatchBlock: (
srcBlock: BlockIdentity,
batch: IBatchBlock | Array<IBatchBlock>,
opts?: Partial<{ before: boolean; sibling: boolean }>
) => Promise<Array<BlockEntity> | null>
updateBlock: (
srcBlock: BlockIdentity,
content: string,
opts?: Partial<{ properties: {} }>
) => Promise<void>
removeBlock: (srcBlock: BlockIdentity) => Promise<void>
getBlock: (
srcBlock: BlockIdentity | EntityID,
opts?: Partial<{ includeChildren: boolean }>
) => Promise<BlockEntity | null>
setBlockCollapsed: (
uuid: BlockUUID,
opts?: { flag: boolean | 'toggle' }
) => Promise<void>
getPage: (
srcPage: PageIdentity | EntityID,
opts?: Partial<{ includeChildren: boolean }>
) => Promise<PageEntity | null>
createPage: (
pageName: BlockPageName,
properties?: {},
opts?: Partial<{
redirect: boolean
createFirstBlock: boolean
format: BlockEntity['format']
journal: boolean
}>
) => Promise<PageEntity | null>
deletePage: (pageName: BlockPageName) => Promise<void>
renamePage: (oldName: string, newName: string) => Promise<void>
getAllPages: (repo?: string) => Promise<any>
prependBlockInPage: (page: PageIdentity, content: string, opts?: Partial<{ properties: {} }>) => Promise<BlockEntity | null>
appendBlockInPage: (page: PageIdentity, content: string, opts?: Partial<{ properties: {} }>) => Promise<BlockEntity | null>
getPreviousSiblingBlock: (
srcBlock: BlockIdentity
) => Promise<BlockEntity | null>
getNextSiblingBlock: (srcBlock: BlockIdentity) => Promise<BlockEntity | null>
moveBlock: (
srcBlock: BlockIdentity,
targetBlock: BlockIdentity,
opts?: Partial<{ before: boolean; children: boolean }>
) => Promise<void>
editBlock: (srcBlock: BlockIdentity, opts?: { pos: number }) => Promise<void>
upsertBlockProperty: (
block: BlockIdentity,
key: string,
value: any
) => Promise<void>
removeBlockProperty: (block: BlockIdentity, key: string) => Promise<void>
getBlockProperty: (block: BlockIdentity, key: string) => Promise<any>
getBlockProperties: (block: BlockIdentity) => Promise<any>
scrollToBlockInPage: (
pageName: BlockPageName,
blockId: BlockIdentity,
opts?: { replaceState: boolean }
) => void
openInRightSidebar: (uuid: BlockUUID) => void
/**
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-a-translator
*/
onInputSelectionEnd: IUserHook<{
caret: any
point: { x: number; y: number }
start: number
end: number
text: string
}>
}
/**
* Datascript related APIs
*/
export interface IDBProxy {
/**
* Run a DSL query
* @link https://docs.logseq.com/#/page/queries
* @param dsl
*/
q: <T = any>(dsl: string) => Promise<Array<T> | null>
/**
* Run a datascript query
*/
datascriptQuery: <T = any>(query: string, ...inputs: Array<any>) => Promise<T>
/**
* Hook all transaction data of DB
*/
onChanged: IUserHook<{
blocks: Array<BlockEntity>
txData: Array<IDatom>
txMeta?: { outlinerOp: string; [key: string]: any }
}>
/**
* Subscribe a specific block changed event
*/
onBlockChanged(
uuid: BlockUUID,
callback: (
block: BlockEntity,
txData: Array<IDatom>,
txMeta?: { outlinerOp: string; [key: string]: any }
) => void
): IUserOffHook
}
/**
* Git related APIS
*/
export interface IGitProxy {
/**
* @link https://github.com/desktop/dugite/blob/master/docs/api/exec.md
* @param args
*/
execCommand: (args: string[]) => Promise<IGitResult>
loadIgnoreFile: () => Promise<string>
saveIgnoreFile: (content: string) => Promise<void>
}
/**
* UI related APIs
*/
export type UIMsgOptions = {
key: string
timeout: number // milliseconds. `0` indicate that keep showing
}
export type UIMsgKey = UIMsgOptions['key']
export interface IUIProxy {
showMsg: (
content: string,
status?: 'success' | 'warning' | 'error' | string,
opts?: Partial<UIMsgOptions>
) => Promise<UIMsgKey>
closeMsg: (key: UIMsgKey) => void
}
/**
* Assets related APIs
*/
export interface IAssetsProxy {
listFilesOfCurrentGraph(
exts: string | string[]
): Promise<{
path: string
size: number
accessTime: number
modifiedTime: number
changeTime: number
birthTime: number
}>
}
export interface ILSPluginThemeManager extends EventEmitter {
themes: Map<PluginLocalIdentity, Array<ThemeOptions>>
registerTheme(id: PluginLocalIdentity, opt: ThemeOptions): Promise<void>
unregisterTheme(id: PluginLocalIdentity): Promise<void>
selectTheme(opt?: ThemeOptions): Promise<void>
}
export type LSPluginUserEvents = 'ui:visible:changed' | 'settings:changed'
export interface ILSPluginUser extends EventEmitter<LSPluginUserEvents> {
/**
* Connection status with the main app
*/
connected: boolean
/**
* Duplex message caller
*/
caller: LSPluginCaller
/**
* The plugin configurations from package.json
*/
baseInfo: LSPluginBaseInfo
/**
* The plugin user settings
*/
settings?: LSPluginBaseInfo['settings']
/**
* The main Logseq app is ready to run the plugin
*
* @param model - same as the model in `provideModel`
*/
ready(model?: Record<string, any>): Promise<any>
/**
* @param callback - a function to run when the main Logseq app is ready
*/
ready(callback?: (e: any) => void | {}): Promise<any>
ready(
model?: Record<string, any>,
callback?: (e: any) => void | {}
): Promise<any>
beforeunload: (callback: () => Promise<void>) => void
/**
* Create a object to hold the methods referenced in `provideUI`
*
* @example
* ```ts
* logseq.provideModel({
* openCalendar () {
* console.log('Open the calendar!')
* }
* })
* ```
*/
provideModel(model: Record<string, any>): this
/**
* Set the theme for the main Logseq app
*/
provideTheme(theme: ThemeOptions): this
/**
* Inject custom css for the main Logseq app
*
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-awesome-fonts
* @example
* ```ts
* logseq.provideStyle(`
* @import url("https://at.alicdn.com/t/font_2409735_r7em724douf.css");
* )
* ```
*/
provideStyle(style: StyleString | StyleOptions): this
/**
* Inject custom UI at specific DOM node.
* Event handlers can not be passed by string, so you need to create them in `provideModel`
*
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-a-translator
* @example
* ```ts
* logseq.provideUI({
* key: 'open-calendar',
* path: '#search',
* template: `
* <a data-on-click="openCalendar" onclick="alert('abc')' style="opacity: .6; display: inline-flex; padding-left: 3px;'>
* <i class="iconfont icon-Calendaralt2"></i>
* </a>
* `
* })
* ```
*/
provideUI(ui: UIOptions): this
/**
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-awesome-fonts
*
* @param schemas
*/
useSettingsSchema(schemas: Array<SettingSchemaDesc>): this
/**
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-awesome-fonts
*
* @param attrs
*/
updateSettings(attrs: Record<string, any>): void
onSettingsChanged<T = any>(cb: (a: T, b: T) => void): IUserOffHook
showSettingsUI(): void
hideSettingsUI(): void
setMainUIAttrs(attrs: Record<string, any>): void
/**
* Set the style for the plugin's UI
*
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-awesome-fonts
* @example
* ```ts
* logseq.setMainUIInlineStyle({
* position: 'fixed',
* zIndex: 11,
* })
* ```
*/
setMainUIInlineStyle(style: CSS.Properties): void
/**
* show the plugin's UI
*/
showMainUI(opts?: { autoFocus: boolean }): void
/**
* hide the plugin's UI
*/
hideMainUI(opts?: { restoreEditingCursor: boolean }): void
/**
* toggle the plugin's UI
*/
toggleMainUI(): void
isMainUIVisible: boolean
resolveResourceFullUrl(filePath: string): string
App: IAppProxy & Record<string, any>
Editor: IEditorProxy & Record<string, any>
DB: IDBProxy
Git: IGitProxy
UI: IUIProxy
FileStorage: LSPluginFileStorage
Experiments: LSPluginExperiments
}