Skip to content

Workflow 服务 API

Workflow family 用来接入宿主和外部世界:上传、布局、持久化、分享、剪贴板、导入导出都属于这一层。

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

WorkflowServicePlugin

ts
interface WorkflowServicePlugin {
  manifest: PluginManifest
  importers?: readonly DescriptorImporter[]
  exporters?: readonly DescriptorExporter[]
  clipboard?: ClipboardService
  layout?: readonly LayoutService[]
  persistence?: PersistenceService
  share?: ShareService
  upload?: UploadService
  activate?: (ctx: PluginActivateContext) => void | Promise<void>
}

宿主通常通过 optionalPlugins 注入 workflow:

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

UploadService

图片或大文件上传应由宿主接管。返回值必须包含最终可访问 URL。

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

PersistenceService

持久化服务负责保存和读取整篇文档。

ts
export const persistenceWorkflow: WorkflowServicePlugin = {
  manifest: { id: 'host:workflow.persistence', name: 'Host Persistence', version: '1.0.0' },
  persistence: {
    id: 'host:persistence',
    async save(ctx) {
      const snapshot = ctx.store.snapshot()
      return new Blob([JSON.stringify(snapshot)], { type: 'application/json' })
    },
    async load(ctx, source) {
      const snapshot = JSON.parse(await source.text())
      return snapshot.nodes
    },
  },
}

组件 ref 上的 saveDocumentWithWorkflow()loadDocumentWithWorkflow(file) 会读取当前激活的 persistence service。没有注册 persistence 时返回 null

ShareService

分享服务负责生成 URL、二维码数据或可上传的 Blob。

ts
export const shareWorkflow: WorkflowServicePlugin = {
  manifest: { id: 'host:workflow.share', name: 'Host Share', version: '1.0.0' },
  share: {
    id: 'host:share',
    async share(ctx, nodeIds) {
      const snapshot = ctx.store.snapshot()
      const res = await fetch('/api/share', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ snapshot, nodeIds }),
      })
      const data = await res.json()
      return { url: data.url }
    },
  },
}

组件 ref 上的 shareDocumentWithWorkflow(nodeIds?) 返回 { url?: string, blob?: Blob } | null

LayoutService

布局服务用于分子或对象的自动排布、美化、避让等场景。

ts
const layoutWorkflow: WorkflowServicePlugin = {
  manifest: { id: 'host:workflow.layout', name: 'Host Layout', version: '1.0.0' },
  layout: [
    {
      id: 'host:layout.compact',
      async apply(ctx, nodeIds, options) {
        console.log('layout target', nodeIds, options)
      },
    },
  ],
}

组件 ref 上的 runWorkflowLayout(nodeIds?) 会调用 workflow registry 中的 layout 服务。

ClipboardService

Clipboard service 用于跨应用 rich-clip 或业务格式剪贴板。

ts
const clipboardWorkflow: WorkflowServicePlugin = {
  manifest: { id: 'host:workflow.clipboard', name: 'Host Clipboard', version: '1.0.0' },
  clipboard: {
    id: 'host:clipboard',
    async write(ctx, nodes) {
      await navigator.clipboard.writeText(JSON.stringify(nodes))
    },
    async read() {
      const text = await navigator.clipboard.readText()
      return JSON.parse(text)
    },
  },
}

Importers 和 exporters

importersexporters 让宿主注册自定义格式。它们通过 descriptor/workflow registry 查询进入 shell 或 helper,而不是把格式逻辑写进 core。

设计边界

  • 上传、保存、分享、业务格式转换属于宿主 workflow。
  • 编辑器 core 只提供稳定的文档、selection、command、scene 和 transaction 入口。
  • workflow helper 是 nullable:父组件必须处理返回 null 的情况。

Released under GPL-3.0-only.