Przeglądaj źródła

Use `noSpellCheckProp` NodeProp to exclude node types from spell check (#21335)

GitOrigin-RevId: 91ba72285b0f01c3c00fdb1a64c30e9ff67f72f5
Alf Eaton 1 rok temu
rodzic
commit
c0d6a9c5f0

+ 19 - 0
services/web/frontend/js/features/source-editor/languages/latex/latex-language.ts

@@ -10,6 +10,7 @@ import {
   getFoldRange,
 } from '../../utils/tree-query'
 import { closeBracketConfig } from './close-bracket-config'
+import { noSpellCheckProp } from '@/features/source-editor/utils/node-props'
 
 const styleOverrides: Record<string, any> = {
   DocumentClassCtrlSeq: t.keyword,
@@ -118,6 +119,24 @@ export const LaTeXLanguage = LRLanguage.define({
           return content
         },
       }),
+      // disable spell check in these node types when they're inside these parents (empty string = any parent)
+      noSpellCheckProp.add({
+        BibKeyArgument: [['']],
+        BibliographyArgument: [['']],
+        BibliographyStyleArgument: [['']],
+        DocumentClassArgument: [['']],
+        LabelArgument: [['']],
+        PackageArgument: [['']],
+        RefArgument: [['']],
+        OptionalArgument: [
+          ['DocumentClass'],
+          ['IncludeGraphics'],
+          ['LineBreak'],
+          ['UsePackage'],
+        ],
+        ShortTextArgument: [['Date']],
+        TextArgument: [['TabularEnvironment', 'BeginEnv']],
+      }),
       // TODO: does this override groups defined in the grammar?
       NodeProp.group.add(type => {
         const types = []

+ 4 - 0
services/web/frontend/js/features/source-editor/lezer-latex/latex.grammar

@@ -87,6 +87,7 @@
     AuthorCtrlSeq,
     AffilCtrlSeq,
     AffiliationCtrlSeq,
+    DateCtrlSeq,
     MaketitleCtrlSeq,
     TextColorCtrlSeq,
     ColorBoxCtrlSeq,
@@ -245,6 +246,9 @@ KnownCommand<ArgumentType> {
     Affiliation {
         AffiliationCtrlSeq optionalWhitespace? OptionalArgument? optionalWhitespace? TextArgument
     } |
+    Date {
+        DateCtrlSeq optionalWhitespace? OptionalArgument? optionalWhitespace? ShortTextArgument
+    } |
     DocumentClass {
         DocumentClassCtrlSeq optionalWhitespace? OptionalArgument?
         DocumentClassArgument { ShortTextArgument }

+ 2 - 0
services/web/frontend/js/features/source-editor/lezer-latex/tokens.mjs

@@ -25,6 +25,7 @@ import {
   AuthorCtrlSeq,
   AffilCtrlSeq,
   AffiliationCtrlSeq,
+  DateCtrlSeq,
   DocumentClassCtrlSeq,
   UsePackageCtrlSeq,
   HrefCtrlSeq,
@@ -546,6 +547,7 @@ const otherKnowncommands = {
   '\\author': AuthorCtrlSeq,
   '\\affil': AffilCtrlSeq,
   '\\affiliation': AffiliationCtrlSeq,
+  '\\date': DateCtrlSeq,
   '\\documentclass': DocumentClassCtrlSeq,
   '\\usepackage': UsePackageCtrlSeq,
   '\\href': HrefCtrlSeq,

+ 9 - 0
services/web/frontend/js/features/source-editor/utils/node-props.ts

@@ -0,0 +1,9 @@
+import { NodeProp } from '@lezer/common'
+
+/**
+ * A node prop that contains an array, each item of which is an array of parent node types that's
+ * passed to [matchContext](https://lezer.codemirror.net/docs/ref/#common.SyntaxNodeRef.matchContext)
+ * to test whether the node matches the given context. If so, the text in the node is excluded from spell checking.
+ * An empty string is treated as a wildcard, so `[['']]` indicates that the node type should always be excluded.
+ */
+export const noSpellCheckProp = new NodeProp<string[][]>()

+ 6 - 13
services/web/frontend/js/features/source-editor/utils/tree-operations/text.ts

@@ -3,6 +3,7 @@ import { Line } from '@codemirror/state'
 import { EditorView } from '@codemirror/view'
 import { SyntaxNodeRef } from '@lezer/common'
 import OError from '@overleaf/o-error'
+import { noSpellCheckProp } from '@/features/source-editor/utils/node-props'
 
 /* A convenient wrapper around 'Normal' tokens */
 export class NormalTextSpan {
@@ -39,18 +40,6 @@ export class NormalTextSpan {
   }
 }
 
-const NotNormalNodeAncestors = [
-  'Include',
-  'Input',
-  'IncludeGraphics',
-  'Cite',
-  'LabelArgument',
-  'UsePackage',
-  'PackageArgument',
-  'EnvNameGroup',
-  'RefArgument',
-]
-
 export const getNormalTextSpansFromLine = (
   view: EditorView,
   line: Line
@@ -64,7 +53,11 @@ export const getNormalTextSpansFromLine = (
     from: lineStart,
     to: lineEnd,
     enter: (node: SyntaxNodeRef) => {
-      if (NotNormalNodeAncestors.includes(node.type.name)) {
+      if (
+        node.type.prop(noSpellCheckProp)?.some(context => {
+          return node.matchContext(context)
+        })
+      ) {
         return false
       }
       if (node.type.name === 'Normal') {