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

如何获取Monaco Editor拖拽虚线标记的行号以插入文本引用?

实现拖拽图片到Monaco Editor插入Markdown引用的方案

核心思路

利用Monaco Editor内置的位置检测API获取拖拽时的光标位置,结合拖拽事件完成文本插入,同时避免react-dropzone与Monaco的事件冲突。

具体步骤

1. 获取Monaco Editor实例

使用React的useRef保存编辑器实例,方便后续调用核心API:

import { useRef, useEffect } from 'react';
import { Editor } from '@monaco-editor/react';

const ImageDropEditor = () => {
  const editorRef = useRef(null);

  const handleEditorMount = (editor) => {
    editorRef.current = editor;
  };

  return (
    <Editor
      onMount={handleEditorMount}
      language="markdown"
      // 其他配置(如主题、默认内容)
    />
  );
};

2. 监听编辑器的Drop事件

直接给编辑器DOM节点绑定drop事件,让Monaco自动处理拖拽时的虚线标记,同时在事件中完成图片插入逻辑:

useEffect(() => {
  const editor = editorRef.current;
  if (!editor) return;

  const handleDrop = (event) => {
    event.preventDefault(); // 阻止浏览器默认的文件打开行为
    const files = Array.from(event.dataTransfer.files);
    const imageFile = files.find(file => file.type.startsWith('image/'));
    if (!imageFile) return;

    // 关键:获取拖拽虚线标记对应的位置
    const dropPosition = editor.getPositionAt(event.clientX, event.clientY);
    if (!dropPosition) return;

    // 替换为你的实际图片上传逻辑,拿到图片CDN地址
    const uploadImage = async (file) => {
      // 示例:模拟上传接口返回地址
      return `https://your-cdn-service.com/images/${file.name}`;
    };

    uploadImage(imageFile).then(imageUrl => {
      // 生成Markdown图片引用格式
      const markdownImage = `![${imageFile.name}](${imageUrl})`;
      // 插入到编辑器对应位置
      editor.executeEdits('insert-image', [
        {
          range: new window.monaco.Range(
            dropPosition.lineNumber,
            dropPosition.column,
            dropPosition.lineNumber,
            dropPosition.column
          ),
          text: markdownImage,
        },
      ]);
    });
  };

  const domNode = editor.getDomNode();
  domNode.addEventListener('drop', handleDrop);

  // 组件卸载时清理事件监听
  return () => domNode.removeEventListener('drop', handleDrop);
}, []);

3. 兼容react-dropzone(可选)

如果需要在编辑器外区域也支持拖拽上传,可保留react-dropzone,但让它忽略编辑器内的拖拽操作:

import { useDropzone } from 'react-dropzone';

const ImageDropEditor = () => {
  // ... 前面的editorRef和handleEditorMount逻辑

  const { getRootProps, getInputProps } = useDropzone({
    accept: { 'image/*': [] },
    // 拖拽到编辑器上时,拒绝Dropzone处理
    isDragRejected: (event) => {
      const editorDom = editorRef.current?.getDomNode();
      return editorDom && editorDom.contains(event.target);
    },
    onDrop: (acceptedFiles) => {
      // 处理编辑器外的拖拽上传逻辑(如弹窗提示、批量上传)
    },
  });

  return (
    <div {...getRootProps()} style={{ padding: '16px' }}>
      <input {...getInputProps()} />
      <Editor onMount={handleEditorMount} />
    </div>
  );
};

关键API说明

  • editor.getPositionAt(clientX, clientY):将鼠标的客户端坐标转换为编辑器内的IPosition对象,包含lineNumber(行号)和column(列号),对应你看到的跟随鼠标的虚线标记位置。
  • editor.executeEdits(editLabel, edits):高效修改编辑器内容,仅替换指定范围的文本,避免全量刷新编辑器内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 03:21:06