Просмотр исходного кода

[cm6] Add Tilde to the LaTeX grammar (#13740)

GitOrigin-RevId: 98a2e968056ba4d6e36310d4ea0f7ff2f25e373a
Alf Eaton 3 лет назад
Родитель
Сommit
e7d36903bb

+ 10 - 0
services/web/frontend/js/features/source-editor/extensions/visual/atomic-decorations.ts

@@ -49,6 +49,7 @@ import { EditableInlineGraphicsWidget } from './visual-widgets/editable-inline-g
 import { CloseBrace, OpenBrace } from '../../lezer-latex/latex.terms.mjs'
 import { FootnoteWidget } from './visual-widgets/footnote'
 import { getListItems } from '../toolbar/lists'
+import { TildeWidget } from './visual-widgets/tilde'
 
 type Options = {
   fileTreeManager: {
@@ -684,6 +685,15 @@ export const atomicDecorations = (options: Options) => {
               )
             }
           }
+        } else if (nodeRef.type.is('Tilde')) {
+          // a tilde (non-breaking space)
+          if (shouldDecorate(state, nodeRef)) {
+            decorations.push(
+              Decoration.replace({
+                widget: new TildeWidget(),
+              }).range(nodeRef.from, nodeRef.to)
+            )
+          }
         } else if (nodeRef.type.is('Caption')) {
           if (shouldDecorate(state, nodeRef)) {
             // a caption

+ 1 - 0
services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/character.ts

@@ -31,6 +31,7 @@ const SUBSTITUTIONS = new Map([
   ['\\%', '\u0025'],
   ['\\_', '\u005F'],
   ['\\}', '\u007D'],
+  ['\\~', '\u007E'],
   ['\\&', '\u0026'],
   ['\\#', '\u0023'],
   ['\\{', '\u007B'],

+ 13 - 0
services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/tilde.ts

@@ -0,0 +1,13 @@
+import { WidgetType } from '@codemirror/view'
+
+export class TildeWidget extends WidgetType {
+  toDOM() {
+    const element = document.createElement('span')
+    element.textContent = '\xa0' // ' ' but not using innerHTML
+    return element
+  }
+
+  eq() {
+    return true
+  }
+}

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

@@ -165,6 +165,7 @@ export const LaTeXLanguage = LRLanguage.define({
           t.literal,
         MathDelimiter: t.literal,
         DoubleDollar: t.keyword,
+        Tilde: t.keyword,
         Comment: t.comment,
         'UsePackage/OptionalArgument/ShortOptionalArg/Normal': t.attributeValue,
         'UsePackage/ShortTextArgument/ShortArg/Normal': t.tagName,

+ 6 - 2
services/web/frontend/js/features/source-editor/lezer-latex/latex.grammar

@@ -114,7 +114,7 @@
     Whitespace { $[ \t]+ }
     NewLine { "\n" }
     BlankLine { "\n" "\n"+ }
-    Normal { ![\\{}\[\]$&#^_% \t\n] ![\\{}\[\]$&#^_%\t\n]* }  // allow ~ space in normal text
+    Normal { ![\\{}\[\]$&~#^_% \t\n] ![\\{}\[\]$&~#^_%\t\n]* }  // everything is normal text, except these characters
     @precedence { CtrlSeq, CtrlSym, BlankLine, NewLine, Whitespace, Normal }
 
     OpenBrace[closedBy=CloseBrace] { "{" }
@@ -128,11 +128,12 @@
 
     Number { $[0-9]+ ("." $[0-9]*)? }
     MathSpecialChar { $[^_=<>()\-+/*]+ }  // FIXME not all of these are special
-    MathChar { ![0-9^_=<>()\-+/*\\{}\[\]\n$%&]+ }
+    MathChar { ![0-9^_=<>()\-+/*\\{}\[\]\n$%&~]+ }
 
     @precedence { Number, MathSpecialChar, MathChar }
 
     Ampersand { "&" }
+    Tilde { "~" }
 
     EnvName {  $[a-zA-Z]+ $[*]? }
 }
@@ -338,6 +339,7 @@ textBase {
     | Normal
     | Whitespace
     | Ampersand
+    | Tilde
     )
 }
 
@@ -454,6 +456,7 @@ DefinitionFragment {
     | CloseBracket
     | "#" // macro character
     | Ampersand // for tables
+    | Tilde // unbreakable space
     | "_" | "^" // other math chars
     | SectioningCommand<
         BookCtrlSeq |
@@ -625,6 +628,7 @@ Math {
     | OpenBracket
     | CloseBracket
     | Ampersand
+    | Tilde
     | Label {
         LabelCtrlSeq optionalWhitespace? OptionalArgument? LabelArgument
     }

+ 12 - 0
services/web/test/frontend/features/source-editor/components/codemirror-editor-visual.spec.tsx

@@ -474,6 +474,18 @@ describe('<CodeMirrorEditor/> in Visual mode', function () {
     cy.get('.ol-cm-author').eq(1).should('contain', 'AuthorNeX')
   })
 
+  describe('handling of special characters', function () {
+    it('decorates a tilde with a non-breaking space', function () {
+      cy.get('@first-line').type('Test~test')
+      cy.get('@first-line').should('have.text', 'Test\xa0test')
+    })
+
+    it('decorates a backslash-prefixed tilde with a tilde', function () {
+      cy.get('@first-line').type('Test\\~test')
+      cy.get('@first-line').should('have.text', 'Test~test')
+    })
+  })
+
   // TODO: \input
   // TODO: Math
   // TODO: Abstract