Fast Car

Back

Mintlify 是一个现代化的技术写作产品,支持使用 MDX 写文档,界面简洁易用,针对需要写公开文档的技术工作非常友好。作为一名全栈工程师和 Mintlify 的深度用户,我在日常技术写作过程中发现了许多降低写作效率的细节问题。

技术写作者应该把重心放在内容架构和核心价值传达上,而不是把时间花费在细枝末节的检查校对上。受到 Notion、飞书等现代 WYSIWYG 编辑器的启发,我决定将这种流畅的写作体验引入到 VSCode 中,让 Mintlify 文档写作回归本质:专注于思考如何进行内容架构,引导读者了解文档内容的核心价值。

今天要介绍的 SlashCommand 功能,正是这一理念的完美体现。通过 CompletionItemProvider 实现的智能斜杠命令系统,让技术写作变得如丝般顺滑。

演示和下载#

功能点详解#

用户痛点分析#

在传统的 Markdown/MDX 写作过程中,技术写作者经常面临以下痛点:

  1. 组件插入繁琐:需要手动输入完整的 Mintlify 组件标签,容易出错
  2. 语法记忆负担:各种组件的属性和语法需要反复查阅文档
  3. 写作流程中断:频繁切换到文档查看组件用法,打断思路
  4. 代码块配置复杂:不同语言的代码块需要配置各种参数

设计思路#

SlashCommand 功能的设计灵感来源于现代 WYSIWYG 编辑器:

  • Notion 的斜杠命令系统:输入 / 即可快速插入各种内容块
  • 飞书文档 的智能提示:根据上下文提供相关的内容建议
  • 现代编辑器 的分类组织:将功能按类别清晰组织,便于查找

核心设计原则:

  1. 零记忆负担:所有组件和语法都通过智能提示提供
  2. 分类清晰:按功能类型组织命令,快速定位
  3. 即插即用:选择即插入,支持 Snippet 占位符
  4. 上下文感知:根据当前编辑环境智能过滤命令

架构图解#

整体架构图#

graph TB A[用户输入 '/'] --> B[SlashCommandCompletionItemProvider] B --> C[上下文检查] C --> D{是否在有效位置?} D -->|否| E[不提供补全] D -->|是| F[生成补全项列表] F --> G[AI Commands] F --> H[Basic Commands] F --> I[Mintlify Components] F --> J[Code Blocks] G --> K[显示分类补全列表] H --> K I --> K J --> K K --> L[用户选择] L --> M{命令类型?} M -->|Snippet| N[插入代码片段] M -->|Command| O[执行VSCode命令]

工作流程图#

sequenceDiagram participant U as 用户 participant E as VSCode编辑器 participant P as SlashCommandProvider participant C as 补全系统 U->>E: 输入 '/' E->>P: 触发 provideCompletionItems P->>P: 检查当前行前缀 P->>P: 验证上下文环境 alt 在引号或括号内 P->>C: 返回空列表 else 有效位置 P->>P: 创建分类补全项 P->>P: 设置排序和过滤 P->>C: 返回补全列表 C->>E: 显示智能提示 E->>U: 展示分类命令列表 U->>E: 选择命令 alt Snippet类型 E->>E: 插入代码片段 else Command类型 E->>E: 执行VSCode命令 end end

命令分类结构图#

graph LR A[SlashCommand] --> B[AI Commands] A --> C[Basic Commands] A --> D[Mintlify Components] A --> E[Code Blocks] B --> B1[✨ Write with AI] C --> C1[📊 Insert Table] C --> C2[📈 Current Date] C --> C3[⏰ Current DateTime] D --> D1[🧩 Note] D --> D2[🧩 Tip] D --> D3[🧩 Warning] D --> D4[🧩 Info] D --> D5[📋 Accordion] D --> D6[📑 Tabs] E --> E1[💻 Basic Code Block] E --> E2[💻 Code with Title] E --> E3[💻 Code with Focus] E --> E4[💻 Code with Line Numbers]

代码实现#

核心 CompletionItemProvider 实现#

class SlashCommandCompletionItemProvider implements vscode.CompletionItemProvider {
    provideCompletionItems(
        document: vscode.TextDocument, 
        position: vscode.Position, 
        token: vscode.CancellationToken,
        context: vscode.CompletionContext
    ): Thenable<vscode.CompletionItem[]> {
        
        const line = document.lineAt(position.line);
        const prefix = line.text.substring(0, position.character);
        
        // 只在行首或空白字符后触发斜杠命令
        if (!prefix.trim().endsWith('/')) {
            return Promise.resolve([]);
        }

        // 上下文环境检查:避免在引号或括号内触发
        const inParentheses = this.isInParentheses(prefix);
        const inQuotes = this.isInQuotes(prefix);
        
        if (inParentheses || inQuotes) {
            return Promise.resolve([]);
        }

        // 生成分类补全项
        const completionItems = this.createCategorizedCompletions();
        return Promise.resolve(completionItems);
    }
}
typescript

分类补全项创建#

private createCategorizedCompletions(): vscode.CompletionItem[] {
    const completionItems: vscode.CompletionItem[] = [];
    
    // 定义各类命令
    const aiCommands = [{
        label: '✨ Write with AI',
        detail: 'AI-powered writing assistant',
        description: 'Generate content with artificial intelligence',
        command: 'flashMintlify.writeWithAI',
        insertText: ''
    }];
    
    const componentCommands = [{
        label: '🧩 Note',
        detail: 'Insert note callout',
        description: 'Note callout component',
        insertText: '<Note>\n${1:This adds a note in the content}\n</Note>',
        kind: vscode.CompletionItemKind.Snippet
    }];
    
    // 创建分类函数
    const createCategoryItems = (commands: any[], categoryPrefix: string, categoryName: string) => {
        const items: vscode.CompletionItem[] = [];
        
        // 添加分类标题(分隔符效果)
        const separator = new vscode.CompletionItem(
            `────────── ${categoryName} ──────────`,
            vscode.CompletionItemKind.Text
        );
        separator.sortText = `${categoryPrefix}000`;
        items.push(separator);
        
        // 添加命令项
        commands.forEach((cmd, index) => {
            const item = new vscode.CompletionItem(
                cmd.label, 
                cmd.kind || vscode.CompletionItemKind.Function
            );
            
            // 设置详细信息
            item.detail = cmd.detail;
            item.documentation = new vscode.MarkdownString(cmd.description);
            
            // 处理不同类型的命令
            if (cmd.command) {
                // 执行命令类型
                item.insertText = '';
                item.command = {
                    command: cmd.command,
                    title: cmd.label
                };
            } else {
                // 插入文本类型
                if (cmd.insertText.includes('$')) {
                    item.insertText = new vscode.SnippetString(cmd.insertText);
                } else {
                    item.insertText = cmd.insertText;
                }
            }
            
            // 设置排序和删除触发字符
            item.sortText = `${categoryPrefix}${String(index + 1).padStart(3, '0')}`;
            item.additionalTextEdits = [
                vscode.TextEdit.delete(new vscode.Range(
                    position.line, position.character - 1,
                    position.line, position.character
                ))
            ];
            
            items.push(item);
        });
        
        return items;
    };
    
    // 创建各分类的补全项
    const aiItems = createCategoryItems(aiCommands, '1', 'AI');
    const componentItems = createCategoryItems(componentCommands, '3', 'Mintlify Components');
    
    completionItems.push(...aiItems, ...componentItems);
    return completionItems;
}
typescript

注册 CompletionItemProvider#

function createCompletionProviders() {
    // 注册斜杠命令提供器
    const slashCommandProvider = vscode.languages.registerCompletionItemProvider(
        [{ language: 'mdx', scheme: 'file' }, { language: 'markdown', scheme: 'file' }],
        new SlashCommandCompletionItemProvider(),
        '/'  // 触发字符
    );
    
    return [slashCommandProvider];
}

export function activate(context: vscode.ExtensionContext) {
    context.subscriptions.push(
        ...createCompletionProviders()
    );
}
typescript

关键实现要点#

  1. 触发字符设置:使用 '/' 作为触发字符,当用户输入斜杠时自动触发补全
  2. 上下文检查:通过检查前缀内容,避免在不合适的位置(如引号内)触发补全
  3. 分类组织:使用分隔符和排序前缀实现清晰的分类显示
  4. 双重模式:支持 Snippet 插入和 Command 执行两种模式
  5. 用户体验:自动删除触发的斜杠字符,提供无缝的插入体验

简单总结#

SlashCommand 功能成功将现代 WYSIWYG 编辑器的流畅体验引入到 VSCode 的技术写作环境中。通过 CompletionItemProvider 的巧妙实现,我们实现了:

  1. 零学习成本:熟悉 Notion 的用户可以无缝上手
  2. 高效写作:大幅减少组件插入的时间和出错率
  3. 分类清晰:智能分类让功能查找更加便捷
  4. 扩展性强:可以轻松添加新的命令类型和功能

这个功能对技术写作效率的提升是显著的,让写作者能够专注于内容本身,而不是被技术细节所困扰。在 AI IDE 如 Cursor 的加持下,整个开发过程变得更加高效,从需求分析到代码实现,AI 助手提供了强有力的支持。

后续可以改进的方向包括:

  • 增加更多 Mintlify 组件的支持
  • 实现基于上下文的智能推荐
  • 添加自定义命令配置功能
  • 集成 AI 写作助手的实际功能

通过这样的功能创新,FlashMintlify 插件正在成为技术写作者的得力助手,让 Mintlify 文档写作变得更加高效和愉悦。

(Part3)用 AI IDE 实现 VSCode 插件系列:SlashCommand 让技术写作如丝般顺滑
https://astro-pure.js.org/blog/vscode-extension/p3-slash-command-completion-provider
Author Oliver Yeung
Published at 2025年9月7日
Comment seems to stuck. Try to refresh?✨