diff --git a/web/cm_plugins/line_wrapper.ts b/web/cm_plugins/line_wrapper.ts index e91ed242..da475fa7 100644 --- a/web/cm_plugins/line_wrapper.ts +++ b/web/cm_plugins/line_wrapper.ts @@ -7,7 +7,6 @@ interface WrapElement { selector: string; class: string; nesting?: boolean; - disableSpellCheck?: boolean; } export function lineWrapper(wrapElements: WrapElement[]) { @@ -18,10 +17,6 @@ export function lineWrapper(wrapElements: WrapElement[]) { syntaxTree(state).iterate({ enter: ({ type, from, to }) => { for (const wrapElement of wrapElements) { - const spellCheckAttributes = wrapElement.disableSpellCheck - ? { attributes: { spellcheck: "false" } } - : {}; - if (type.name == wrapElement.selector) { if (wrapElement.nesting) { elementStack.push(type.name); @@ -36,7 +31,6 @@ export function lineWrapper(wrapElements: WrapElement[]) { widgets.push( Decoration.line({ class: cls, - ...spellCheckAttributes, }).range(doc.lineAt(idx).from), ); idx += line.length + 1; diff --git a/web/cm_plugins/spell_checking.ts b/web/cm_plugins/spell_checking.ts new file mode 100644 index 00000000..2505385b --- /dev/null +++ b/web/cm_plugins/spell_checking.ts @@ -0,0 +1,25 @@ +import type { EditorState, Range } from "@codemirror/state"; +import { Decoration } from "@codemirror/view"; +import { syntaxTree } from "@codemirror/language"; +import { decoratorStateField } from "./util.ts"; + +export function disableSpellcheck(selectors: string[]) { + return decoratorStateField((state: EditorState) => { + const widgets: Range[] = []; + syntaxTree(state).iterate({ + enter: ({ type, from, to }) => { + for (const selector of selectors) { + if (type.name === selector) { + widgets.push( + Decoration.mark({ + attributes: { spellcheck: "false" }, + }).range(from, to), + ); + } + } + }, + }); + + return Decoration.set(widgets, true); + }); +} diff --git a/web/editor_state.ts b/web/editor_state.ts index 9cc2940a..87f70ff6 100644 --- a/web/editor_state.ts +++ b/web/editor_state.ts @@ -53,6 +53,7 @@ import { extendedMarkdownLanguage } from "$common/markdown_parser/parser.ts"; import { parseCommand } from "$common/command.ts"; import { safeRun } from "$lib/async.ts"; import { codeCopyPlugin } from "./cm_plugins/code_copy.ts"; +import { disableSpellcheck } from "./cm_plugins/spell_checking.ts"; export function createEditorState( client: Client, @@ -159,11 +160,7 @@ export function createEditorState( { selector: "Blockquote", class: "sb-line-blockquote" }, { selector: "Task", class: "sb-line-task" }, { selector: "CodeBlock", class: "sb-line-code" }, - { - selector: "FencedCode", - class: "sb-line-fenced-code", - disableSpellCheck: true, - }, + { selector: "FencedCode", class: "sb-line-fenced-code" }, { selector: "Comment", class: "sb-line-comment" }, { selector: "BulletList", class: "sb-line-ul" }, { selector: "OrderedList", class: "sb-line-ol" }, @@ -171,9 +168,9 @@ export function createEditorState( { selector: "FrontMatter", class: "sb-frontmatter", - disableSpellCheck: true, }, ]), + disableSpellcheck(["InlineCode", "CodeText", "FrontMatter"]), keyBindings, EditorView.domEventHandlers({ // This may result in duplicated touch events on mobile devices