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

ACE编辑器Mermaid图自动补全出现前缀重复问题求助

Ace编辑器Mermaid自动补全重复标记问题解决

问题描述

为Ace编辑器添加Mermaid图自动补全功能,当前实现代码如下:

const mermaids = Object.entries({
    "mermaid graph": `graph LR\n    x --> y`,
}).map(([name, autocompletion]) => ({
    caption: name,
    meta: name,
    value: "```mermaid\n" + autocompletion + "\n```"
}));

aceeditor.setOptions({
    enableBasicAutocompletion: [{
        getCompletions: (editor, session, pos, prefix, callback) => {
            callback(null, [
                ...mermaids
            ])
        }
    }],
    enableSnippets: false,
    enableLiveAutocompletion: true
});

遇到的问题:

  • 输入graph或mermaid回车触发补全时,功能正常(仅光标位置需优化);
  • 输入回车触发补全时,补全内容会追加在原有之后,导致重复标记,示例如下:
``````mermaid
graph LR
    x --> y
## 高效修正方法
核心思路:在补全逻辑中判断当前输入上下文,动态调整补全内容的格式,避免重复添加```。

修改`getCompletions`函数,检查当前行是否已经输入了```,如果是,则移除补全内容开头的```标记:
```javascript
aceeditor.setOptions({
    enableBasicAutocompletion: [{
        getCompletions: (editor, session, pos, prefix, callback) => {
            const currentLine = session.getLine(pos.row);
            // 动态调整补全项的value
            const adjustedMermaids = mermaids.map(item => {
                if (currentLine.trim() === "```") {
                    // 去掉开头的```,避免重复
                    return {
                        ...item,
                        value: item.value.replace(/^```/, '')
                    };
                }
                return item;
            });
            callback(null, adjustedMermaids);
        }
    }],
    enableSnippets: false,
    enableLiveAutocompletion: true
});

补全完成后的兜底处理方案

如果上述方法无法覆盖所有场景,可以通过监听Ace编辑器的change事件,在补全完成后检查并清理重复标记:

editor.on("change", (event) => {
    const session = editor.getSession();
    const { start, end } = event.range;
    const changedText = event.data.text;

    // 仅处理包含mermaid标记的插入操作
    if (changedText.includes("```mermaid")) {
        // 检查前一行是否是重复的```
        const prevRow = start.row - 1;
        if (prevRow >= 0) {
            const prevLine = session.getLine(prevRow);
            if (prevLine.trim() === "```") {
                // 删除前一行的重复标记
                session.remove({
                    start: { row: prevRow, column: 0 },
                    end: { row: prevRow, column: prevLine.length }
                });
            }
        }
    }
});

更优实现方案:使用Ace代码片段(Snippets)

Ace的Snippets功能支持更灵活的补全控制,包括光标位置、动态替换内容,能更好适配不同触发场景:

  1. 启用Snippets功能:
aceeditor.setOptions({
    enableBasicAutocompletion: true,
    enableSnippets: true,
    enableLiveAutocompletion: true
});
  1. 注册针对不同触发词的Mermaid片段:
// 获取编辑器的代码片段管理器
const snippetManager = ace.require("ace/snippets").snippetManager;

// 注册针对`graph`和`mermaid`的完整片段
snippetManager.register({
    name: "markdown",
    snippets: [
        {
            caption: "Mermaid Graph",
            tabTrigger: "graph",
            snippet: '```mermaid\n    graph LR\n        ${1:x} --> ${2:y}\n```',
            description: "Insert a Mermaid flow graph"
        },
        {
            caption: "Mermaid Graph",
            tabTrigger: "mermaid",
            snippet: '```mermaid\n    graph LR\n        ${1:x} --> ${2:y}\n```',
            description: "Insert a Mermaid flow graph"
        },
        // 针对```的片段,直接补全mermaid内容和结尾标记
        {
            caption: "Mermaid Graph",
            tabTrigger: "```",
            snippet: 'mermaid\n    graph LR\n        ${1:x} --> ${2:y}\n```',
            description: "Insert a Mermaid flow graph after triple backticks"
        }
    ]
});

这种方式不仅能避免重复标记问题,还支持通过Tab键跳转光标到可编辑位置(${1:x}和${2:y}),提升编辑体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 03:15:50