From 14a5c62836dac92f234cc264ee03424024adede5 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Sat, 4 Jan 2025 17:58:33 +0200 Subject: [PATCH 1/2] Share the JS check --- src/index.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5be8993..96fe7f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,11 +2,19 @@ import { javascriptLanguage } from "@codemirror/lang-javascript"; import { syntaxTree } from "@codemirror/language"; import { EditorSelection, + type EditorState, type SelectionRange, type StateCommand, } from "@codemirror/state"; import type { KeyBinding } from "@codemirror/view"; +const able = (state: EditorState, range: SelectionRange) => { + // Don't do anything if we're not in JavaScript mode. + // This should also cover TypeScript, which is just + // JavaScript with extra configuration. + return range.empty && javascriptLanguage.isActiveAt(state, range.from) +} + /** * This is modeled after the CodeMirror Markdown mode's * ability to continue lists and blockquotes. It's meant to be bound @@ -22,11 +30,9 @@ export const insertNewlineContinueComment: StateCommand = ({ const { doc } = state; let dont: null | { range: SelectionRange } = null; const changes = state.changeByRange((range) => { - // Don't do anything if we're not in JavaScript mode. - // This should also cover TypeScript, which is just - // JavaScript with extra configuration. - if (!range.empty || !javascriptLanguage.isActiveAt(state, range.from)) + if (!able(state, range)) return (dont = { range }); + const pos = range.from; const line = doc.lineAt(pos); @@ -82,10 +88,7 @@ export const maybeCloseBlockComment: StateCommand = ({ state, dispatch }) => { const { doc } = state; let dont: null | { range: SelectionRange } = null; const changes = state.changeByRange((range) => { - // Don't do anything if we're not in JavaScript mode. - // This should also cover TypeScript, which is just - // JavaScript with extra configuration. - if (!range.empty || !javascriptLanguage.isActiveAt(state, range.from)) + if (!able(state, range)) return (dont = { range }); const pos = range.from; const line = doc.lineAt(pos); From 7fe72c7699fc274720a34ead574adabb8f5a3d66 Mon Sep 17 00:00:00 2001 From: Matt Mundell Date: Sat, 4 Jan 2025 17:59:34 +0200 Subject: [PATCH 2/2] Support any language with JS style block comments Caveat is that the language must provide commentTokens languageData, and must use a syntax node called BlockComment for block comments. --- README.md | 3 ++- src/index.ts | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index dff6ea3..6788b5e 100644 --- a/README.md +++ b/README.md @@ -62,4 +62,5 @@ extensions: [ ``` And that's it! This will only do anything if your CodeMirror -is using the JavaScript or TypeScript mode. +is using a language that supports `/* */` style block comments, +like JavaScript and TypeScript. diff --git a/src/index.ts b/src/index.ts index 96fe7f8..3220803 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,11 +8,28 @@ import { } from "@codemirror/state"; import type { KeyBinding } from "@codemirror/view"; +// commentTokens: {line: "//", block: {open: "/*", close: "*/"}}, +interface Block { + open: string | null, + close: string | null +} +interface CommentTokens { + line: string | null, + block: Block | null +} + const able = (state: EditorState, range: SelectionRange) => { - // Don't do anything if we're not in JavaScript mode. - // This should also cover TypeScript, which is just - // JavaScript with extra configuration. - return range.empty && javascriptLanguage.isActiveAt(state, range.from) + if (range.empty) { + const data = state.languageDataAt("commentTokens", range.from); + for (let i = 0; i < data.length; i++) { + const block = data[i]?.block; + if (block + && (block.open === "/*") + && (block.close === "*/")) + return true; + } + } + return false } /**