我正在使用monaco-editor,我发现在后续版本中上下文菜单中添加了剪切和复制功能。我想从上下文菜单中删除这两个选项。请告诉我如何实现?
我正在使用monaco-editor,我发现在后续版本中上下文菜单中添加了剪切和复制功能。我想从上下文菜单中删除这两个选项。请告诉我如何实现?
import * as actions from "monaco-editor/esm/vs/platform/actions/common/actions";
let menus = actions.MenuRegistry._menuItems
let contextMenuEntry = [...menus].find(entry => entry[0]._debugName == "EditorContext")
let contextMenuLinks = contextMenuEntry[1]
let removableIds = ["editor.action.clipboardCopyAction", "editor.action.clipboardPasteAction"]
let removeById = (list, ids) => {
let node = list._first
do {
let shouldRemove = ids.includes(node.element?.command?.id)
if (shouldRemove) { list._remove(node) }
} while ((node = node.next))
}
removeById(contextMenuLinks, removableIds)
您可以从actions.js
中的MenuRegistry
访问可用的菜单功能:
import * as actions from "monaco-editor/esm/vs/platform/actions/common/actions"
let menus = actions.MenuRegistry._menuItems
["MenubarEditMenu", "CommandPalette", "EditorContext", ...]
要特别访问和修改上下文菜单,我们可以在菜单映射中找到它:let contextMenuEntry = [...menus].find(entry => entry[0]._debugName == "EditorContext")
let contextMenuLinks = contextMenuEntry[1]
LinkedList
,每个node
包含一个element
和对prev
和next
节点的引用,但它配备了一些实用程序方法,使得更容易进行推理。let allCommandIds = [...contextMenuLinks].map(el => el.command?.id)
let removableIds = [
"editor.action.clipboardCopyAction",
"editor.action.clipboardPasteAction",
]
node.element
}},但{{link2:_remove()
}}函数接受整个节点,因此我们需要以与之前略有不同的方式进行迭代。以下是一个循环遍历所有节点并删除每个节点的函数:let removeById = (list, ids) => {
let node = list._first;
do {
let shouldRemove = ids.includes(node.element?.command?.id)
if (shouldRemove) { list._remove(node) }
} while ((node = node.next))
}
And then call like this:
removeById(contextMenuLinks, removableIds)
我在浏览器中尝试了这段代码,它可以正常工作。
// Hide from cut on
.context-view li.action-item:nth-child(n + 9) {
display: none !important;
}
// Show command palette
.context-view li.action-item:last-child {
display: flex !important;
}
monacoOptions = {
// other options
contextmenu: false
}
请参阅有关 IEditorConstructionOptions
> contextmenu
的文档。
编辑:此答案现已过时,有关最新解决方法,请查看:https://github.com/microsoft/monaco-editor/issues/1567
这里的答案已经过时了,actions.MenuRegistry._menuItems似乎不再返回任何内容。编辑器也已经移动到shadowroot,破坏了css方法。
以下方法可行:
const shadowroot = document.querySelector(".shadow-root-host").shadowRoot
const RemoveContextMenuIndexes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 13];
for (const itemIndex of RemoveContextMenuIndexes) {
shadowroot.querySelector(`ul.actions-container > li.action-item:nth-child(${itemIndex})`).style.display = "none";
}
以下内容适用于我,并且是从KyleMit的此答案进行修改的,因为原文对我不起作用。
import * as actions from 'monaco-editor/esm/vs/platform/actions/common/actions';
const idsToRemove = ['editor.action.clipboardCopyAction', 'editor.action.clipboardCutAction'];
actions.MenuRegistry._menuItems[1] = actions.MenuRegistry._menuItems[1]
.filter(menuItem => !menuItem.command || !idsToRemove.includes(menuItem.command.id));
最終我採用了一種基於Nighfalls答案稍微修改的方法
onContextMenu
來訪問代碼編輯器。當用戶打開上下文菜單時,將運行此操作。在用戶第一次打開上下文菜單之前,DOM中不存在影子根。querySelector
找到影子根和上下文菜單項,因為在用戶打開上下文菜單之前,影子根不存在於DOM中。style.display
會導致typescript linting問題。在元素本身上使用.remove()
會導致菜單中其他更下面的動作項目的懸停/高亮顯示存在奇怪的錯誤。最終需要.remove()
操作項元素內部的元素。 this.codeEditorInstance.onContextMenu(() => {
setTimeout(() => {
const shadowroot = document.querySelector('.shadow-root-host')?.shadowRoot;
if (shadowroot) {
const RemoveContextMenuIndexes = [3];
for (const itemIndex of RemoveContextMenuIndexes) {
const el = shadowroot.querySelector(
`ul.actions-container > li.action-item:nth-child(${itemIndex})`
);
if (el) {
el.querySelector('a')
?.querySelectorAll('span')
.forEach((s) => s.remove());
el.querySelector('a')?.remove();
}
}
}
}, 0);
});