Skip to content

Plugin Families API

Molio 的公共扩展契约收口到三类 plugin families:

  1. ObjectTypePlugin:新增或接入对象类型。
  2. UIContributionPlugin:贡献 toolbar、菜单、选区栏、快捷键、leftDock 和 HUD slot。
  3. WorkflowServicePlugin:接入上传、布局、持久化、分享、剪贴板、导入导出等宿主服务。

装载层

用途
core编辑器必需能力,如 molecule 和 connector。
builtin默认随包提供、可被宿主覆盖的能力。
optional宿主或下游产品追加的业务扩展。

普通宿主使用 optionalPlugins

vue
<MolEditor :optional-plugins="[hostUiPlugin, hostWorkflowPlugin]" />

高级宿主如果要完全替换 builtin 层,才传 plugins

UIContributionPlugin

ts
import { EDITOR_COMMANDS, type UIContributionPlugin } from '@shangchien/molio'

export const hostUiPlugin: UIContributionPlugin = {
  manifest: { id: 'host:ui', name: 'Host UI', version: '1.0.0' },
  toolbar: [
    {
      id: 'host:toolbar.autofit',
      slot: 'top-utility',
      label: '适配视图',
      commandId: EDITOR_COMMANDS.viewAutofit,
    },
  ],
  shortcuts: [
    {
      id: 'host:shortcut.autofit',
      keys: 'mod+shift+0',
      scope: 'global',
      commandId: EDITOR_COMMANDS.viewAutofit,
    },
  ],
}

toolbar slot

slot位置
left-tools左侧主工具区。
left-secondary左侧次级工具区。
center-actions顶部主操作区。
right-actions右侧动作区。
top-utility顶部右侧工具区。
bottom-status底部状态区。

leftDock 和 slots

leftDock.panelComponentslots.component 是字符串 ID,宿主需要通过 uiComponents 映射成真实 Vue 组件。

ts
import InspectorPanel from './InspectorPanel.vue'

const uiComponents = {
  'host:inspector': InspectorPanel,
}

const hostUiPlugin: UIContributionPlugin = {
  manifest: { id: 'host:ui.inspector', name: 'Inspector', version: '1.0.0' },
  leftDock: [
    {
      id: 'host:left-dock.inspector',
      label: 'Inspector',
      panelComponent: 'host:inspector',
    },
  ],
}
vue
<MolEditor :optional-plugins="[hostUiPlugin]" :ui-components="uiComponents" />

ObjectTypePlugin

Object plugin 由 descriptor 和 runtime 两部分组成。descriptor 声明对象类型;runtime 把对象接入 hit、select、drag、tool 和 scene 生命周期。

ts
import { ref } from 'vue'
import type { ObjectControllerRuntime, ObjectDescriptor, ObjectTypePlugin } from '@shangchien/molio'

type NotePayload = {
  kind: 'host:note'
  text: string
}

const descriptor: ObjectDescriptor<NotePayload> = {
  id: 'host:note',
  kind: 'host:note',
  family: 'leaf',
  title: 'Host Note',
  schemaVersion: 1,
}

export const noteObjectPlugin: ObjectTypePlugin = {
  manifest: { id: 'host:note.object', name: 'Host Note Object', version: '1.0.0' },
  descriptors: [descriptor],
  createRuntime(ctx) {
    const selectedIds = ref(new Set<string>())
    const controller: ObjectControllerRuntime = {
      key: 'host:note',
      descriptor,
      actions: {},
      selectedIds,
      hitObject: () => null,
      isSelected: id => selectedIds.value.has(id),
      selectObject: id => {
        selectedIds.value = id ? new Set([id]) : new Set()
      },
      clearSelection: () => {
        selectedIds.value = new Set()
      },
      getSelectedObject: () => null,
      beginDrag: () => false,
      updateDrag: () => {},
      endDrag: () => {},
      cancelDrag: () => {},
    }

    ctx.registerDisposable({ dispose: () => selectedIds.value.clear() })
    return { controllers: [controller] }
  },
}

WorkflowServicePlugin

Workflow 负责宿主工作流,不应该写进 core。

ts
import type { WorkflowServicePlugin } from '@shangchien/molio'

export const hostWorkflowPlugin: WorkflowServicePlugin = {
  manifest: { id: 'host:workflow', name: 'Host Workflow', version: '1.0.0' },
  upload: {
    id: 'host:upload',
    accept: ['image/*'],
    async upload(file) {
      const formData = new FormData()
      formData.append('file', file)
      const res = await fetch('/api/upload', { method: 'POST', body: formData })
      const data = await res.json()
      return { url: data.url }
    },
  },
}

更多 workflow 示例见 Workflow 服务

可见性控制

UI contribution 可以通过 visibilityvisibledisabled 按当前选区、只读状态或工具状态控制显示。

ts
{
  id: 'host:selection.delete',
  label: '删除',
  commandId: EDITOR_COMMANDS.selectionDelete,
  visibility: ctx => ({ visible: ctx.selectionCount > 0, enabled: !ctx.readonly }),
}

建议

  • 新对象类型用 ObjectTypePlugin
  • 新按钮、菜单、快捷键、面板和 HUD 用 UIContributionPlugin
  • 上传、保存、分享、布局、导入导出用 WorkflowServicePlugin
  • 只有缺少稳定扩展点时,才考虑向 core 增加最小通用能力。

Released under GPL-3.0-only.