* 处理源码文本输入
()
| 864 | * 处理源码文本输入 |
| 865 | */ |
| 866 | private handleSourceTextInput(): void { |
| 867 | if (!this.sourceTextElement || this.updating) return; |
| 868 | |
| 869 | // 从所有子 div 中收集文本内容 |
| 870 | const lines: string[] = []; |
| 871 | const childDivs = this.sourceTextElement.querySelectorAll("div.milkup-with-line-number"); |
| 872 | childDivs.forEach((div) => { |
| 873 | lines.push(div.textContent || ""); |
| 874 | }); |
| 875 | const text = lines.join("\n"); |
| 876 | |
| 877 | const pos = this.getPos(); |
| 878 | if (pos === undefined) return; |
| 879 | |
| 880 | // 保存光标位置 |
| 881 | const selection = window.getSelection(); |
| 882 | let cursorOffset = 0; |
| 883 | if (selection && selection.rangeCount > 0) { |
| 884 | const range = selection.getRangeAt(0); |
| 885 | if (range.startContainer.nodeType === Node.TEXT_NODE) { |
| 886 | cursorOffset = range.startOffset; |
| 887 | // 计算相对于整个文本的偏移量 |
| 888 | let node: Node | null = range.startContainer; |
| 889 | while (node && node !== this.sourceTextElement && node.previousSibling) { |
| 890 | node = node.previousSibling; |
| 891 | cursorOffset += node.textContent?.length || 0; |
| 892 | } |
| 893 | } |
| 894 | } |
| 895 | |
| 896 | this.updating = true; |
| 897 | |
| 898 | // 检查是否是完整的代码块格式(必须有开头和结尾的 ```) |
| 899 | const fenceMatch = text.match(/^```([^\n]*?)\n([\s\S]*?)\n```$/); |
| 900 | |
| 901 | if (fenceMatch) { |
| 902 | // 仍然是完整的代码块格式,更新内容 |
| 903 | const [, language, content] = fenceMatch; |
| 904 | const tr = this.view.state.tr; |
| 905 | let needsUpdate = false; |
| 906 | |
| 907 | // 更新语言属性 |
| 908 | const normalizedLang = language || ""; |
| 909 | if (normalizedLang !== this.node.attrs.language) { |
| 910 | tr.setNodeMarkup(pos, null, { |
| 911 | ...this.node.attrs, |
| 912 | language: normalizedLang, |
| 913 | }); |
| 914 | needsUpdate = true; |
| 915 | } |
| 916 | |
| 917 | // 更新内容 |
| 918 | if (content !== this.node.textContent) { |
| 919 | const start = pos + 1; |
| 920 | const end = pos + 1 + this.node.content.size; |
| 921 | tr.replaceWith(start, end, content ? this.view.state.schema.text(content) : []); |
| 922 | needsUpdate = true; |
| 923 | } |
no test coverage detected