* 显示右键菜单
(e: MouseEvent)
| 1163 | * 显示右键菜单 |
| 1164 | */ |
| 1165 | private async showContextMenu(e: MouseEvent): Promise<void> { |
| 1166 | // 移除已存在的右键菜单 |
| 1167 | this.hideContextMenu(); |
| 1168 | |
| 1169 | const isHeaderContextMenu = !!(e.target instanceof HTMLElement |
| 1170 | ? e.target.closest(".milkup-code-block-header") |
| 1171 | : null); |
| 1172 | |
| 1173 | const menu = document.createElement("div"); |
| 1174 | menu.className = "milkup-context-menu"; |
| 1175 | |
| 1176 | // 检查是否有选区 |
| 1177 | const { main } = this.cm.state.selection; |
| 1178 | const hasSelection = !main.empty; |
| 1179 | |
| 1180 | // 检查剪贴板是否有内容(文本或图片) |
| 1181 | let hasClipboardContent = true; // 默认启用粘贴 |
| 1182 | try { |
| 1183 | const items = await navigator.clipboard.read(); |
| 1184 | hasClipboardContent = items.length > 0; |
| 1185 | } catch { |
| 1186 | // 如果 read() 不支持,尝试 readText() |
| 1187 | try { |
| 1188 | const text = await navigator.clipboard.readText(); |
| 1189 | hasClipboardContent = text.length > 0; |
| 1190 | } catch { |
| 1191 | hasClipboardContent = true; // 默认启用粘贴 |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | // 复制 |
| 1196 | const copyItem = this.createContextMenuItem("复制", !hasSelection, () => { |
| 1197 | const selectedText = this.cm.state.sliceDoc(main.from, main.to); |
| 1198 | navigator.clipboard.writeText(selectedText); |
| 1199 | this.hideContextMenu(); |
| 1200 | }); |
| 1201 | menu.appendChild(copyItem); |
| 1202 | |
| 1203 | // 剪切 |
| 1204 | const cutItem = this.createContextMenuItem("剪切", !hasSelection, () => { |
| 1205 | const selectedText = this.cm.state.sliceDoc(main.from, main.to); |
| 1206 | navigator.clipboard.writeText(selectedText); |
| 1207 | this.cm.dispatch({ |
| 1208 | changes: { from: main.from, to: main.to, insert: "" }, |
| 1209 | }); |
| 1210 | this.hideContextMenu(); |
| 1211 | }); |
| 1212 | menu.appendChild(cutItem); |
| 1213 | |
| 1214 | // 粘贴 - 使用 Clipboard API 读取文本 |
| 1215 | const pasteItem = this.createContextMenuItem("粘贴", !hasClipboardContent, async () => { |
| 1216 | this.hideContextMenu(); |
| 1217 | this.cm.focus(); |
| 1218 | try { |
| 1219 | const text = await navigator.clipboard.readText(); |
| 1220 | if (text) { |
| 1221 | const { main } = this.cm.state.selection; |
| 1222 | this.cm.dispatch({ |
no test coverage detected