(node: ProseMirrorNode, view: ProseMirrorView, getPos: () => number | undefined)
| 542 | private sourceViewUnsubscribe: (() => void) | null = null; |
| 543 | |
| 544 | constructor(node: ProseMirrorNode, view: ProseMirrorView, getPos: () => number | undefined) { |
| 545 | this.node = node; |
| 546 | this.view = view; |
| 547 | this.getPos = getPos; |
| 548 | this.languageCompartment = new Compartment(); |
| 549 | this.themeCompartment = new Compartment(); |
| 550 | this.lineNumbersCompartment = new Compartment(); |
| 551 | this.searchHighlightCompartment = new Compartment(); |
| 552 | |
| 553 | // 检测当前主题 |
| 554 | const isDark = detectDarkTheme(); |
| 555 | |
| 556 | // 规范化语言名称 |
| 557 | const normalizedLang = normalizeLanguage(node.attrs.language); |
| 558 | if (normalizedLang !== node.attrs.language) { |
| 559 | requestAnimationFrame(() => { |
| 560 | const pos = this.getPos(); |
| 561 | if (pos !== undefined) { |
| 562 | this.view.dispatch( |
| 563 | this.view.state.tr.setNodeMarkup(pos, null, { |
| 564 | ...this.node.attrs, |
| 565 | language: normalizedLang, |
| 566 | }) |
| 567 | ); |
| 568 | } |
| 569 | }); |
| 570 | } |
| 571 | |
| 572 | // 用户手动创建的 mermaid 代码块(内容为空),使用混合模式方便编辑 |
| 573 | if (normalizedLang === "mermaid" && !node.textContent) { |
| 574 | this.mermaidDisplayMode = "mixed"; |
| 575 | } |
| 576 | |
| 577 | // 创建容器 |
| 578 | this.dom = document.createElement("div"); |
| 579 | this.dom.className = "milkup-code-block"; |
| 580 | |
| 581 | // 创建头部(语言选择器) |
| 582 | this.headerElement = this.createHeader(normalizedLang); |
| 583 | this.dom.appendChild(this.headerElement); |
| 584 | |
| 585 | // 头部右键菜单 |
| 586 | this.headerElement.addEventListener("contextmenu", (e) => { |
| 587 | e.preventDefault(); |
| 588 | e.stopPropagation(); |
| 589 | this.showContextMenu(e); |
| 590 | }); |
| 591 | |
| 592 | // 创建 CodeMirror 编辑器容器 |
| 593 | this.editorContainer = document.createElement("div"); |
| 594 | this.editorContainer.className = "milkup-code-block-editor"; |
| 595 | this.dom.appendChild(this.editorContainer); |
| 596 | |
| 597 | this.cm = new EditorView({ |
| 598 | state: CMEditorState.create({ |
| 599 | doc: node.textContent, |
| 600 | extensions: [ |
| 601 | history(), |
nothing calls this directly
no test coverage detected