🐛 Fixed the issue of highlightActiveLine and selected background color conflicts

This commit is contained in:
2025-04-24 22:13:08 +08:00
parent f41a13c217
commit dcf07c9106
2 changed files with 50 additions and 38 deletions

View File

@@ -5,6 +5,7 @@ import {
drawSelection, drawSelection,
dropCursor, dropCursor,
EditorView, EditorView,
highlightActiveLine,
highlightActiveLineGutter, highlightActiveLineGutter,
highlightSpecialChars, highlightSpecialChars,
keymap, keymap,
@@ -12,22 +13,17 @@ import {
rectangularSelection, rectangularSelection,
} from '@codemirror/view'; } from '@codemirror/view';
import {Compartment, EditorState, Extension} from '@codemirror/state'; import {Compartment, EditorState, Extension} from '@codemirror/state';
import {baseDark} from "@/editor/theme/base-dark"; import {baseDark, customHighlightActiveLine} from "@/editor/theme/base-dark";
import { import {
bracketMatching, bracketMatching,
defaultHighlightStyle, defaultHighlightStyle,
foldGutter, foldGutter,
foldKeymap, foldKeymap,
indentOnInput, indentOnInput,
syntaxHighlighting, indentUnit,
indentUnit syntaxHighlighting
} from '@codemirror/language'; } from '@codemirror/language';
import { import {defaultKeymap, history, historyKeymap, indentSelection,} from '@codemirror/commands';
defaultKeymap,
history,
historyKeymap,
indentSelection,
} from '@codemirror/commands';
import {highlightSelectionMatches, searchKeymap} from '@codemirror/search'; import {highlightSelectionMatches, searchKeymap} from '@codemirror/search';
import {autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap} from '@codemirror/autocomplete'; import {autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap} from '@codemirror/autocomplete';
import {lintKeymap} from '@codemirror/lint'; import {lintKeymap} from '@codemirror/lint';
@@ -55,7 +51,7 @@ const handleWheel = (event: WheelEvent) => {
if (event.ctrlKey) { if (event.ctrlKey) {
// 阻止默认行为(防止页面缩放) // 阻止默认行为(防止页面缩放)
event.preventDefault(); event.preventDefault();
// 根据滚轮方向增大或减小字体 // 根据滚轮方向增大或减小字体
if (event.deltaY < 0) { if (event.deltaY < 0) {
// 向上滚动,增大字体 // 向上滚动,增大字体
@@ -73,26 +69,26 @@ const tabHandler = (view: EditorView): boolean => {
if (!view.state.selection.main.empty) { if (!view.state.selection.main.empty) {
return indentSelection(view); return indentSelection(view);
} }
// 获取当前的tabSize值 // 获取当前的tabSize值
const currentTabSize = editorStore.tabSize; const currentTabSize = editorStore.tabSize;
// 创建相应数量的空格 // 创建相应数量的空格
const spaces = ' '.repeat(currentTabSize); const spaces = ' '.repeat(currentTabSize);
// 在光标位置插入空格 // 在光标位置插入空格
const { state, dispatch } = view; const {state, dispatch} = view;
dispatch(state.update(state.replaceSelection(spaces), { scrollIntoView: true })); dispatch(state.update(state.replaceSelection(spaces), {scrollIntoView: true}));
return true; return true;
}; };
// 获取Tab相关的扩展 // 获取Tab相关的扩展
const getTabExtensions = (): Extension[] => { const getTabExtensions = (): Extension[] => {
const extensions: Extension[] = []; const extensions: Extension[] = [];
// 设置缩进单位 // 设置缩进单位
const tabSize = editorStore.tabSize; const tabSize = editorStore.tabSize;
extensions.push(tabSizeCompartment.of(indentUnit.of(' '.repeat(tabSize)))); extensions.push(tabSizeCompartment.of(indentUnit.of(' '.repeat(tabSize))));
// 如果启用了Tab缩进添加自定义Tab键映射 // 如果启用了Tab缩进添加自定义Tab键映射
if (editorStore.enableTabIndent) { if (editorStore.enableTabIndent) {
extensions.push(tabKeyCompartment.of(keymap.of([{ extensions.push(tabKeyCompartment.of(keymap.of([{
@@ -102,7 +98,7 @@ const getTabExtensions = (): Extension[] => {
} else { } else {
extensions.push(tabKeyCompartment.of([])); extensions.push(tabKeyCompartment.of([]));
} }
return extensions; return extensions;
}; };
@@ -130,6 +126,8 @@ const createEditor = () => {
rectangularSelection(), rectangularSelection(),
crosshairCursor(), crosshairCursor(),
highlightSelectionMatches(), highlightSelectionMatches(),
customHighlightActiveLine,
highlightActiveLine(),
keymap.of([ keymap.of([
...closeBracketsKeymap, ...closeBracketsKeymap,
...defaultKeymap, ...defaultKeymap,
@@ -156,13 +154,13 @@ const createEditor = () => {
state, state,
parent: editorElement.value parent: editorElement.value
}); });
// 将编辑器实例保存到store // 将编辑器实例保存到store
editorStore.setEditorView(view); editorStore.setEditorView(view);
// 初始化统计 // 初始化统计
updateStats(); updateStats();
// 应用初始字体大小 // 应用初始字体大小
editorStore.applyFontSize(); editorStore.applyFontSize();
}; };
@@ -170,12 +168,12 @@ const createEditor = () => {
// 更新统计信息 // 更新统计信息
const updateStats = () => { const updateStats = () => {
if (!editorStore.editorView) return; if (!editorStore.editorView) return;
const view = editorStore.editorView; const view = editorStore.editorView;
const state = view.state; const state = view.state;
const doc = state.doc; const doc = state.doc;
const text = doc.toString(); const text = doc.toString();
// 计算选中的字符数 // 计算选中的字符数
let selectedChars = 0; let selectedChars = 0;
const selections = state.selection; const selections = state.selection;
@@ -185,7 +183,7 @@ const updateStats = () => {
selectedChars += range.to - range.from; selectedChars += range.to - range.from;
} }
} }
editorStore.updateDocumentStats({ editorStore.updateDocumentStats({
lines: doc.lines, lines: doc.lines,
characters: text.length, characters: text.length,
@@ -196,22 +194,22 @@ const updateStats = () => {
// 动态更新Tab配置不需要重建编辑器 // 动态更新Tab配置不需要重建编辑器
const updateTabConfig = () => { const updateTabConfig = () => {
if (!editorStore.editorView) return; if (!editorStore.editorView) return;
// 更新Tab大小配置 // 更新Tab大小配置
const tabSize = editorStore.tabSize; const tabSize = editorStore.tabSize;
const view = editorStore.editorView; const view = editorStore.editorView;
// 更新indentUnit配置 // 更新indentUnit配置
view.dispatch({ view.dispatch({
effects: tabSizeCompartment.reconfigure(indentUnit.of(' '.repeat(tabSize))) effects: tabSizeCompartment.reconfigure(indentUnit.of(' '.repeat(tabSize)))
}); });
// 更新Tab键映射 // 更新Tab键映射
const tabKeymap = editorStore.enableTabIndent const tabKeymap = editorStore.enableTabIndent
? keymap.of([{ key: "Tab", run: tabHandler }]) ? keymap.of([{key: "Tab", run: tabHandler}])
: []; : [];
view.dispatch({ view.dispatch({
effects: tabKeyCompartment.reconfigure(tabKeymap) effects: tabKeyCompartment.reconfigure(tabKeymap)
}); });
@@ -220,7 +218,7 @@ const updateTabConfig = () => {
// 重新配置编辑器(仅在必要时完全重建) // 重新配置编辑器(仅在必要时完全重建)
const reconfigureEditor = () => { const reconfigureEditor = () => {
if (!editorStore.editorView) return; if (!editorStore.editorView) return;
// 尝试动态更新配置 // 尝试动态更新配置
updateTabConfig(); updateTabConfig();
}; };
@@ -237,10 +235,10 @@ watch(() => editorStore.enableTabIndent, () => {
onMounted(() => { onMounted(() => {
// 创建编辑器 // 创建编辑器
createEditor(); createEditor();
// 添加滚轮事件监听 // 添加滚轮事件监听
if (editorElement.value) { if (editorElement.value) {
editorElement.value.addEventListener('wheel', handleWheel, { passive: false }); editorElement.value.addEventListener('wheel', handleWheel, {passive: false});
} }
}); });
@@ -249,7 +247,7 @@ onBeforeUnmount(() => {
if (editorElement.value) { if (editorElement.value) {
editorElement.value.removeEventListener('wheel', handleWheel); editorElement.value.removeEventListener('wheel', handleWheel);
} }
if (editorStore.editorView) { if (editorStore.editorView) {
editorStore.editorView.destroy(); editorStore.editorView.destroy();
editorStore.setEditorView(null); editorStore.setEditorView(null);

View File

@@ -9,10 +9,11 @@ export const config = {
background: '#252B37', background: '#252B37',
foreground: '#9BB586', foreground: '#9BB586',
selection: '#1A5888', selection: '#1A5888',
selectionMatch: 'rgba(26, 88, 136, 0.5)',
cursor: '#F8F8F2', cursor: '#F8F8F2',
dropdownBackground: '#282A36', dropdownBackground: '#282A36',
dropdownBorder: '#191A21', dropdownBorder: '#191A21',
activeLine: '#2E333F', activeLine: 'rgba(46, 51, 63, 0.6)',
lineNumber: '#676d7c', lineNumber: '#676d7c',
lineNumberActive: '#F8F8F2', lineNumberActive: '#F8F8F2',
lineNumberBackground: '#212731', lineNumberBackground: '#212731',
@@ -42,7 +43,10 @@ export const draculaTheme = EditorView.theme({
'.cm-content': {caretColor: config.cursor}, '.cm-content': {caretColor: config.cursor},
'.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor}, '.cm-cursor, .cm-dropCursor': {borderLeftColor: config.cursor},
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {backgroundColor: config.selection},
'&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': {
backgroundColor: `${config.selection} !important`
},
'.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground}, '.cm-panels': {backgroundColor: config.dropdownBackground, color: config.foreground},
'.cm-panels.cm-panels-top': {borderBottom: '2px solid black'}, '.cm-panels.cm-panels-top': {borderBottom: '2px solid black'},
@@ -57,7 +61,11 @@ export const draculaTheme = EditorView.theme({
}, },
'.cm-activeLine': {backgroundColor: config.activeLine}, '.cm-activeLine': {backgroundColor: config.activeLine},
'.cm-selectionMatch': {backgroundColor: config.selection},
'.cm-selectionMatch': {
backgroundColor: `${config.selectionMatch} !important`,
borderRadius: '2px'
},
'&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': { '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': {
backgroundColor: config.matchingBracket, backgroundColor: config.matchingBracket,
@@ -123,6 +131,12 @@ export const draculaHighlightStyle = HighlightStyle.define([
{tag: t.strikethrough, textDecoration: 'line-through'}, {tag: t.strikethrough, textDecoration: 'line-through'},
]) ])
export const customHighlightActiveLine = EditorView.theme({
'.cm-activeLine': {
backgroundColor: config.activeLine,
}
})
export const baseDark: Extension = [ export const baseDark: Extension = [
draculaTheme, draculaTheme,
syntaxHighlighting(draculaHighlightStyle), syntaxHighlighting(draculaHighlightStyle),