子应用monaco editor点击事件不生效
bug描述 子应用里面有monaco editor功能,里面的代码无法编辑
如何复现 给出详细的复现步骤 可以直接拿monaco官网测试,https://microsoft.github.io/monaco-editor/ 将链接嵌入进来,点击中间的代码光标没有出现,但是光标选在代码最后是可以的,添加新的代码也是可以的
错误截图

排查了不是跨域的问题,也不是资源加载的问题,看了下monaco.current.onMouseDown(e)返回的e.target里面是空,但是e.event是正确的内容,还没找到具体是什么原因,请大佬排查一下,用无界把编辑器嵌入主应用来这种需求还是比较常见的
看看 #205 呢
已解决,感谢
同样的问题,谷歌浏览器解决了,但firefox浏览器13.0.1 版本下仍然不可点击
升级monaco版本可以解决 "monaco-editor": "^0.29.0", "monaco-editor-webpack-plugin": "^5.0.0", 但是firefox还是会有同样问题,可以尝试继续升级吧,后续我没尝试
你好 你是怎么解决的 能给个方案吗 有偿 合适请加下企鹅 1036752557 教一下我
import fs from 'fs'
import path from 'path'
/**
* Monaco Editor 0.52.0 + Wujie 最终补丁方案
*
* 问题根源:
* Monaco的_actualDoHitTestWithCaretRangeFromPoint函数内部有Wujie特殊处理,
* 但这个处理有bug - 备用函数f在Wujie环境下返回的Range对象不正确。
*
* 解决方案:
* 不依赖备用函数f,直接让Monaco在Wujie环境下使用document.caretRangeFromPoint,
* 然后我们hijack document.caretRangeFromPoint来支持shadowDOM。
*/
export const patchMonacoEditor = () => {
try {
const cwd = process.cwd()
const filePath = path.resolve(cwd, 'node_modules/monaco-editor/min/vs/editor/editor.main.js')
if (!fs.existsSync(filePath)) {
console.log('❌ Monaco editor file not found:', filePath)
return
}
let content = fs.readFileSync(filePath, 'utf8')
// 创建备份
const backupPath = `${filePath}.backup`
if (!fs.existsSync(backupPath)) {
fs.writeFileSync(backupPath, content)
console.log('✅ 已备份Monaco Editor原始文件')
}
let modified = false
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 修复方案:Hijack document.caretRangeFromPoint 支持shadowDOM
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
const hijackCode = `
;(function(){
if(typeof window!=='undefined'&&window.__POWERED_BY_WUJIE__&&window.__WUJIE&&window.__WUJIE.shadowRoot){
const sr=window.__WUJIE.shadowRoot;
// Hijack document.caretRangeFromPoint to support Wujie shadowDOM
if(!Document.prototype.__originalCaretRangeFromPoint){
Document.prototype.__originalCaretRangeFromPoint=Document.prototype.caretRangeFromPoint;
Document.prototype.caretRangeFromPoint=function(x,y){
try{
// 首先在shadowRoot中查找元素
let el=sr.elementFromPoint(x,y);
if(!el){
// 回退到原始实现
return this.__originalCaretRangeFromPoint.call(this,x,y);
}
// 创建range
const range=this.createRange();
// 遍历找到文本节点
while(el&&el.firstChild){
if(el.firstChild.nodeType===3)break;//TEXT_NODE
el=el.firstChild;
}
// 获取文本节点
let textNode=el&&el.nodeType===3?el:el&&el.firstChild;
// 如果没有文本节点,尝试使用el本身
if(!textNode||textNode.nodeType!==3){
if(el&&el.nodeType===3){
textNode=el;
}else if(el&&el.textContent){
// 最后尝试:获取el的任意文本子节点
const walker=this.createTreeWalker(el,NodeFilter.SHOW_TEXT);
textNode=walker.nextNode();
}
}
// 如果还是没有文本节点,返回null
if(!textNode||textNode.nodeType!==3){
return null;
}
// 🎯 精确计算offset(基于像素位置)
const text=textNode.textContent||'';
let offset=0;
if(text.length>0){
// 使用临时Range测量每个字符的位置
const testRange=this.createRange();
for(let i=0;i<text.length;i++){
testRange.setStart(textNode,i);
testRange.setEnd(textNode,i+1);
const charRect=testRange.getBoundingClientRect();
const charMidpoint=charRect.left+charRect.width/2;
// 如果鼠标在字符左半部分,offset就是i
if(x<charMidpoint){
offset=i;
break;
}
// 否则offset继续向后
offset=i+1;
}
}
range.setStart(textNode,offset);
range.setEnd(textNode,offset);
return range;
}catch(err){
console.error('[Monaco+Wujie] caretRangeFromPoint error:',err);
// 出错时回退到原始实现
return this.__originalCaretRangeFromPoint.call(this,x,y);
}
};
console.log('✅ Monaco+Wujie: Hijacked document.caretRangeFromPoint for shadowDOM support');
}
}
})();
`
// 在文件开头注入
if (!content.includes('__originalCaretRangeFromPoint')) {
content = hijackCode + content
modified = true
console.log('✅ 注入document.caretRangeFromPoint hijack代码')
}
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// 修复MARK正则兼容性
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// const markRegexStr = 'new RegExp("\\bMARK:\\s*(.*)$","d")'
// if (content.includes(markRegexStr)) {
// const markRegexReplacement = `new RegExp("\\bMARK:\\s*(.*)$", (()=>{try{new RegExp('','d');return 'd';}catch(e){return '';}})())`
// content = content.replace(markRegexStr, markRegexReplacement)
// modified = true
// console.log('✅ 修复MARK正则兼容性')
// }
if (modified) {
fs.writeFileSync(filePath, content)
console.log('')
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
console.log('🎉 Monaco Editor补丁应用成功')
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
console.log('')
console.log('补丁内容:')
console.log(' ✓ Hijack document.caretRangeFromPoint')
console.log(' ✓ 在shadowRoot中查找元素')
console.log(' ✓ 创建有效的Range对象')
console.log(' ✓ 完整的错误处理和fallback')
console.log('')
console.log('工作原理:')
console.log(' Monaco调用document.caretRangeFromPoint(x, y)')
console.log(' → 我们的hijack使用shadowRoot.elementFromPoint(x, y)')
console.log(' → 遍历找到文本节点')
console.log(' → 创建有效的range对象')
console.log(' → Monaco后续处理这个range')
console.log('')
} else {
console.log('⚠️ Monaco Editor 补丁未应用任何修改或已存在')
}
} catch (error) {
console.error('❌ Monaco Editor补丁失败:', error)
}
}