You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeMirror如何在注释或元数据中存储并读取信息

针对你的需求,分CodeMirror 6 和 CodeMirror 5 两个主流版本给出实现方案:

CodeMirror 6 实现

CodeMirror 6 没有直接的行级元数据API,你可以通过**行装饰(Decoration)**或者lineAttrs扩展实现图形ID的存储和读取,比官方的Transaction Annotation更适配行级元数据场景。

步骤1:定义装饰字段存储图形ID

import { Decoration, DecorationSet } from "@codemirror/view"
import { StateField, StateEffect } from "@codemirror/state"

// 定义给行加图形ID的效果
const addGraphId = StateEffect.define<{
  line: number,
  graphId: string
}>()
const removeGraphId = StateEffect.define<number>()

// 定义存储所有行图形ID的状态字段
export const graphIdField = StateField.define<DecorationSet>({
  create() {
    return Decoration.none
  },
  update(decos, tr) {
    decos = decos.map(tr.changes)
    for (const e of tr.effects) {
      if (e.is(addGraphId)) {
        const line = tr.state.doc.line(e.value.line)
        decos = decos.update({
          add: [Decoration.line({
            attributes: { "data-graph-id": e.value.graphId },
            graphId: e.value.graphId
          }).range(line.from, line.from)]
        })
      } else if (e.is(removeGraphId)) {
        const line = tr.state.doc.line(e.value)
        decos = decos.update({
          filter: (from, to) => from !== line.from
        })
      }
    }
    return decos
  },
  provide: f => EditorView.decorations.from(f)
})

步骤2:存储图形ID到指定行

你在解析到绘图指令生成图形ID后,调用下面的代码存到对应行:

editor.dispatch({
  effects: addGraphId.of({
    line: 3, // 替换为你的指令行号,从1开始计数
    graphId: "graph_123" // 替换为你的图形ID
  })
})

步骤3:删除行时读取图形ID

监听文档变更事件,遍历被删除的行,读取绑定的图形ID:

import { ViewPlugin, ViewUpdate } from "@codemirror/view"

const deleteGraphListener = ViewPlugin.fromClass(class {
  update(update: ViewUpdate) {
    if (!update.docChanged) return
    // 遍历所有变更范围
    update.changes.iterChanges((fromA, toA) => {
      const startLine = update.startState.doc.lineAt(fromA)
      const endLine = update.startState.doc.lineAt(toA)
      // 遍历所有被删除的行
      for (let lineNum = startLine.number; lineNum <= endLine.number; lineNum++) {
        const line = update.startState.doc.line(lineNum)
        // 读取该行的装饰元数据
        update.startState.field(graphIdField).between(line.from, line.to, (from, to, deco) => {
          if (deco.spec.graphId) {
            // 拿到图形ID,调用你的Canvas删除逻辑
            console.log("需要删除的图形ID:", deco.spec.graphId)
          }
        })
      }
    })
  }
})

最后把graphIdField和deleteGraphListener加入到编辑器的扩展配置即可。

CodeMirror 5 实现

CodeMirror 5 原生提供了行级元数据的读写API,实现更简单:

存储图形ID

// line参数为行号,默认从1开始计数
editor.setLineData(line, { graphId: "graph_123" })

读取并处理删除行的逻辑

editor.on("beforeChange", (cm, change) => {
  // 只处理删除操作
  if (change.origin !== "+delete") return
  const startLine = change.from.line
  const endLine = change.to.line
  for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
    const lineMeta = cm.getLineData(lineNum)
    if (lineMeta?.graphId) {
      // 拿到图形ID调用Canvas删除逻辑
      console.log("需要删除的图形ID:", lineMeta.graphId)
    }
  }
})

内容的提问来源于stack exchange,提问作者Jadon Erwin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 14:24:04