Improve code editor text selection and clean up lint enablement (#37474)

1. Make the content area stretch the box, enabling text selection to
start over empty space.
2. Disable linter for markdown, it can never produce lint errors, this
hides the unnecessary lint gutter on markdown files.
3. Verified all languages linter enablement, all accurate.
4. Refactor `getLinterExtension` to not rely on file extensions.
5. Include jsonc/json5 extensions in regex.

---
This PR was written with the help of Claude Opus 4.7

---------

Co-authored-by: Claude (Opus 4.7) <noreply@anthropic.com>
Co-authored-by: Nicolas <bircni@icloud.com>
This commit is contained in:
silverwind
2026-05-01 19:41:31 +02:00
committed by GitHub
parent deb31d3f30
commit 31cee60cc7
2 changed files with 22 additions and 17 deletions

View File

@@ -24,6 +24,8 @@
font-family: var(--fonts-monospace); font-family: var(--fonts-monospace);
font-size: 12px; font-size: 12px;
max-height: 90vh; max-height: 90vh;
flex: 1;
min-height: 0;
} }
.code-editor-container .cm-editor, .code-editor-container .cm-editor,
@@ -31,24 +33,22 @@
border-radius: 0 0 var(--border-radius) var(--border-radius); border-radius: 0 0 var(--border-radius) var(--border-radius);
} }
.code-editor-container .cm-content,
.code-editor-container .cm-gutter {
min-height: 200px;
}
.code-editor-container .cm-scroller { .code-editor-container .cm-scroller {
overflow: auto; overflow: auto;
line-height: var(--line-height-code); line-height: var(--line-height-code);
flex: 1;
min-height: 0;
}
.code-editor-container .cm-content {
align-self: stretch;
padding: 0;
} }
.code-editor-container .cm-content * { .code-editor-container .cm-content * {
caret-color: inherit; caret-color: inherit;
} }
.code-editor-container .cm-content {
padding: 0;
}
.code-editor-container .cm-cursor, .code-editor-container .cm-cursor,
.code-editor-container .cm-dropCursor { .code-editor-container .cm-dropCursor {
border-left-color: var(--color-caret); border-left-color: var(--color-caret);
@@ -341,6 +341,8 @@
.code-editor-container { .code-editor-container {
position: relative; position: relative;
min-height: 90vh; min-height: 90vh;
display: flex;
flex-direction: column;
} }
.cm-command-palette { .cm-command-palette {

View File

@@ -7,7 +7,7 @@ import type {PaletteCommand} from './command-palette.ts';
import {contextMenu, collectSymbols, selectAllOccurrences} from './context-menu.ts'; import {contextMenu, collectSymbols, selectAllOccurrences} from './context-menu.ts';
import {createJsonLinter, createSyntaxErrorLinter} from './linter.ts'; import {createJsonLinter, createSyntaxErrorLinter} from './linter.ts';
import {clickableUrls, goToDefinitionAt, trimTrailingWhitespaceFromView} from './utils.ts'; import {clickableUrls, goToDefinitionAt, trimTrailingWhitespaceFromView} from './utils.ts';
import type {LanguageDescription} from '@codemirror/language'; import type {LanguageDescription, LanguageSupport} from '@codemirror/language';
import type {Compartment, Extension} from '@codemirror/state'; import type {Compartment, Extension} from '@codemirror/state';
import type {EditorView, ViewUpdate} from '@codemirror/view'; import type {EditorView, ViewUpdate} from '@codemirror/view';
@@ -295,16 +295,19 @@ export async function createCodeEditor(textarea: HTMLTextAreaElement, filenameIn
return editor; return editor;
} }
// files that are JSONC despite having a .json extension // files that the JSON parser is too strict for (comments, trailing commas)
const jsoncFilesRegex = /^([jt]sconfig.*|devcontainer)\.json$/; const jsoncFilesRegex = /^([jt]sconfig.*|devcontainer)\.json$|\.(jsonc|json5)$/i;
async function getLinterExtension(cm: CodemirrorModules, filename: string, loadedLang: {language: unknown} | null): Promise<Extension> { async function getLinterExtension(cm: CodemirrorModules, filename: string, loadedLang: LanguageSupport | null): Promise<Extension> {
const ext = extname(filename).toLowerCase(); if (!loadedLang) return [];
if (ext === '.json' || ext === '.map') { const lang = loadedLang.language;
// StreamLanguage (legacy modes) don't produce Lezer error nodes
if (lang instanceof cm.language.StreamLanguage) return [];
if (lang.name === 'json') {
return jsoncFilesRegex.test(filename) ? [] : [cm.lint.lintGutter(), await createJsonLinter(cm)]; return jsoncFilesRegex.test(filename) ? [] : [cm.lint.lintGutter(), await createJsonLinter(cm)];
} }
// StreamLanguage (legacy modes) don't produce Lezer error nodes // markdown's parser emits no error nodes, and nested code-fence overlays aren't traversed
if (!loadedLang || loadedLang.language instanceof cm.language.StreamLanguage) return []; if (lang.name === 'markdown') return [];
return [cm.lint.lintGutter(), createSyntaxErrorLinter(cm)]; return [cm.lint.lintGutter(), createSyntaxErrorLinter(cm)];
} }