yh-codemirror

wraper codemirror with vue3
2,275
Install
npm install yh-codemirror
Latest Version:1.0.9
Vue:3
Last Updated:Oct 10, 2026
Links: npm
Maintainer: lkyh_fe

yh-codemirror

Vue3 的 CodeMirror6 封装,在全屏 / 美化 / 全选 / 复制 / 清空 等基础能力之上,提供 AI 提示编辑(选中或整篇代码 → 自然语言描述 → AI 改写回写)。

基础用法

<yh-codemirror
  v-model="code"
  :height="500"
  language="javascript"
  :autocomplete="{javascript: myCompletionSource}">
</yh-codemirror>

language 支持 javascript / sql / css / java / html / json,可传数组;不在列表内会取不到语言插件。 autocomplete 只对 javascript 生效(按语言名取,如 {javascript: myCompletionSource})。 不传 aiRequest 就是一个纯编辑器,不会出现任何 AI 入口。

AI 提示编辑

组件本身不内置任何 AI 服务(保持零业务依赖),由宿主通过 aiRequest 注入请求实现。传入 aiRequest 即自动启用:

  • 编辑器右下角出现 AI 入口按钮
  • 快捷键 Ctrl+I(Mac Cmd+I,可通过 aiHotkey 改)唤起输入框
  • 有选区 → 只改写选中代码;无选区 → 按 aiScope 作用于整个文档或光标处插入
  • Enter 发送、Esc 取消;请求中按钮变「停止」,可中断
  • 支持流式:调用 onChunk 逐段返回,编辑器实时写入;非流式则直接返回完整替换文本
  • 自动剥离模型常见的 ```lang ... ``` 包裹
  • 通过 dispatch 写入,保留 CodeMirror 撤销栈,可 Ctrl+Z 回退
  • 历史问答:输入框右上角「历史」可查看本轮会话问过的问题与 AI 的完整回答(可展开、可复制、可清空), 每条前面会显示宿主传入的 aiLocation,建议格式「区域名称 · <按钮/查询条件/字段名称 + 类型> · 编辑器字段名」 (如「区域信息 · 事件按钮 · 点击事件」「区域信息 · 名称字段 · 字段值更改」; 直接在区域事件里提问时没有中间层,就是「区域信息 · 数据初始化」)

历史记录存在 ai-history.js 的模块级单例里(上限 50 条,最新在前)。之所以不放组件内: 配置面板里的编辑器会随切换配置项反复卸载重建,组件内的 ref 一卸载就没了。 代价是同一页面所有编辑器共用一份(未做分组),所以每条都带时间、问题原文和 aiLocation—— 没有归属信息时,一堆「把名称标红」的提问根本分不清是哪块配置。

Props

参数 类型 默认值 说明
aiRequest AiCodeEditRequest - AI 请求函数,传入即启用 AI 编辑
aiHotkey string 'Mod-i' 唤起输入框的快捷键(CodeMirror 键位语法)
aiPlaceholder string 见源码 输入框占位提示
aiScope 'document' | 'cursor' 'document' 无选区时的作用范围
aiPanelSize 'normal' | 'large' 'normal' AI 输入框 / 历史面板的尺寸档位。编辑区被放大时(如 window-form 的「放大」抽屉)传 large
aiWindowId string | number '' AI 上下文用的「所属窗口 ID」。组件不认识任何业务接口,只在 AI 被唤起时通过 ai-activate 把它抛给宿主,由宿主去取窗口配置
aiLocation string '' 这条提问来自哪里(建议「区域名 · 按钮/查询条件/字段名 + 类型 · 编辑器字段名」,如「区域信息 · 事件按钮 · 点击事件」,名称一律取 NAME)。组件只原样记进历史并显示在问题前,不解析其含义

Events

事件 参数 说明
update:modelValue string 代码变更(原有)
ai-activate string | number AI 面板刚打开(携带 aiWindowId),宿主可趁此时预取上下文;aiWindowId 为空时不触发
ai-apply {prompt, text} AI 结果已写入编辑器
ai-error Error AI 请求失败

Expose

openAi(prompt?)、closeAi()、stopAi()、getView()。

接入示例(非流式)

import {YhCodemirror} from 'yh-codemirror';
import type {AiCodeEditRequest} from 'yh-codemirror';

const aiRequest: AiCodeEditRequest = async ({prompt, code, selectedCode, language, signal}) => {
  const res = await fetch('/api/ai/code-edit', {
    method: 'POST',
    signal,
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({prompt, code, selectedCode, language}),
  });
  if (!res.ok) {
    throw new Error('AI 请求失败');
  }
  const data = await res.json();
  // 返回「作用范围的完整替换文本」,组件负责写入
  return data.code;
};

接入示例(流式 SSE)

const aiRequest: AiCodeEditRequest = async ({prompt, selectedCode, signal, onChunk}) => {
  const res = await fetch('/api/ai/code-edit/stream', {
    method: 'POST',
    signal,
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({prompt, code: selectedCode}),
  });
  const reader = res.body!.getReader();
  const decoder = new TextDecoder();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    onChunk?.(decoder.decode(value, {stream: true}));
  }
  // 走 onChunk 时返回值可为空,组件已实时写入编辑器
};

提示:流式场景下 onChunk 传入的是增量片段,组件按累积文本整体覆盖作用区间,因此服务端无需自行做 diff。

Version History

Version Released Vue License
1.0.9 ^3.5.0
1.0.8 ^3.5.0
1.0.7 ^3.5.0
1.0.6 ^3.0.0
1.0.5 3.2.47