前景介绍
故事开始于一个平凡的午后,当阳光透过窗户洒在代码编辑器上,前端开发小 A 忽然眼前一亮,情不自禁地大声赞叹:"Cursor 真是太好用了!"这款 AI 驱动的编辑器让他的代码效率翻倍,但一个棘手的问题却在他脑海中盘旋:他究竟如何才能把 Swagger 中指定模块的 API 接口定义导入到 Cursor 中,让 AI 助手直接基于这些定义来生成和实现代码?
开发时间
MVP 可用 一个小时左右,当前版本 2 天。
开发人员
Cursor Version: Version: 1.0.0 (Universal)
工具形态
悬浮框 +AIChat 对话框
步骤实现
优先考虑通过 MCP 调用 Swagger 并解析特定模块的接口提供给 Cursor,这个方案的优势在于我们已有现成实现,将其注册为 MCP 工具只需简单添加一个装饰器即可完成转换。
然而,实践中发现这种方式对语义解析的要求极高,尤其在模块匹配和模块下接口的精准识别方面。若不进行多轮深度对话,AI 生成的结果往往不尽如人意。为解决这一痛点,我转向了更直观的解决方案——开发浏览器插件实现页面接口的直接选择与抓取,从而获取更精准的结构化数据,大幅提升接口解析的准确性和开发体验。
令人啼笑皆非的是,就在团队还在为接口集成方案激烈讨论时,我们的"外包伙伴" Cursor 默默地等待着指令。短短几分钟的对话和指导后,它就交出了一份令人惊艳的答卷。
所有人好奇地凑到屏幕前,只见一个简洁优雅的操作:鼠标轻轻一划,Swagger 页面上的接口就被选中了,紧接着——砰!Cursor 编辑器自动弹出,接口定义完美呈现。这个看似简单的功能,却恰到好处地解决了团队一直纠结的难题。
"这...这也太快了吧?"有人惊讶地说。
"这就是 Cursor 的魅力,"团队负责人笑着说,"它就像一位得力的外包伙伴,只需简单的指令,就能快速理解需求并交付成果。"
这一刻,办公室里响起了一片赞叹声。谁能想到困扰团队的难题,竟被这位 AI 助手用如此优雅的方式解决了。这或许就是 AI 时代的魅力——有时候,最好的解决方案不在于复杂的架构设计,而是找到一个懂你的好搭档。而 Cursor,正是这样一位既懂技术又懂团队的完美伙伴。
诶~突然灵光一闪! 我们这不是已经整了个剪贴板功能嘛。转念一想...哎哟我去,那些设了权限的机密文档...该不会也能被'顺手牵羊'了吧? 这可是个'神奇的发现'啊,要是真能复制出来,那可就有点意思了~
出来吧,我的如意神剑 Cursor!
......
果不其然,一分钟后,尘埃落定。任务完美达成
卧槽,这威力简直了! 让我们掀开它的神秘面纱,一探究竟... 不得不说,这操作属实秀到我了,高手在民间啊~
// Text selection utilities
export function getSelectedText() {
const selection = window.getSelection();
let text = selection.toString().trim();
// First method: standard selection
if (text && text.length > 0) {
return text;
}
try {
// Second method: extract from range contents
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
const container = range.commonAncestorContainer;
// Create a temporary div to extract text
const tempDiv = document.createElement('div');
tempDiv.appendChild(range.cloneContents());
// Get the text content and clean it
text = (tempDiv.innerText || tempDiv.textContent || '').trim();
text = text.replace(/\u200B/g, '').trim(); // Remove zero-width spaces
if (text && text.length > 0) {
return text;
}
// Third method: try to get text from the element itself
if (container) {
// If selection is within a special element
const targetElement =
container.nodeType === Node.TEXT_NODE ?
container.parentNode :
container;
// Check for special elements
if (targetElement) {
// Try to get text content in various ways
text = targetElement.innerText ||
targetElement.textContent ||
targetElement.getAttribute('data-text') ||
targetElement.value ||
targetElement.getAttribute('value') ||
'';
text = text.trim();
if (text && text.length > 0) {
return text;
}
// If still no text, try to get from parent elements
let parent = targetElement.parentElement;
while (parent && !text) {
text = parent.innerText ||
parent.textContent ||
parent.getAttribute('data-text') ||
parent.value ||
parent.getAttribute('value') ||
'';
text = text.trim();
if (text && text.length > 0) {
return text;
}
parent = parent.parentElement;
}
}
}
}
} catch (e) {
console.error('Error extracting text:', e);
}
return text || '';
}
export function disableCopyProtection() {
// Remove all copy protections
const protectionRemover = () => {
// Enable selection
document.designMode = 'on';
setTimeout(() => {
document.designMode = 'off';
}, 100);
// Remove common protection attributes
document.querySelectorAll('*').forEach(el => {
if (el.style) {
if (el.style.userSelect === 'none') {
el.style.userSelect = 'auto';
}
if (el.style.webkitUserSelect === 'none') {
el.style.webkitUserSelect = 'auto';
}
}
// Remove protection attributes
el.removeAttribute('unselectable');
el.removeAttribute('onselectstart');
el.removeAttribute('oncontextmenu');
el.removeAttribute('oncopy');
el.removeAttribute('oncut');
});
// Allow right-click
document.oncontextmenu = null;
// Allow selection
document.onselectstart = null;
};
// Run protection remover immediately and periodically
protectionRemover();
setInterval(protectionRemover, 1000);
// Override common protection methods
const originalAddEventListener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(type, listener, options) {
if (type === 'copy' || type === 'cut' || type === 'contextmenu' ||
type === 'selectstart' || type === 'mousedown' ||
type === 'keydown' || type === 'dragstart') {
// Skip adding these protection event listeners
console.log(`Blocked protection: ${type}`);
return;
}
return originalAddEventListener.call(this, type, listener, options);
};
}
等等...灵光乍现! 既然能复制,那岂不是...嘿嘿,直接请 AI 大神帮忙解惑也不是不可以? 这波操作可以啊~
咱给团队配个 CTO 当技术马仔~
再怼上满血 DeepSeek V3 引擎 ——
代码跑得比奶茶外卖还快,算法 buff 直接拉满,
CTO 举着键盘喊:"这算力咱可叠明白了!"(狗头)
咱得给 CTO 加个 "防秃金钟罩"~ 免得被累死....
再让我们的 Cursor 员工实现一下 ChatBot 引入逻辑...依然是那么的速度....等等...既然是插件那岂不是...在任何页面都可以无侵入的加载...我好像想到了什么....基于 RAG 岂不是可以做个业务问答?
基于已有的精准测试岂不是可以分析 URL 对应的业务代码?.... 这....
未完待续。。。下班了。。。