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

[cm6] indent figure modal generated code (#13213)

* [cm6] indent figure modal generated code

* fix: prettier

* fix indenting issues

* add licence on top

* fix cypress tests

GitOrigin-RevId: 8f74be537f19c2a29de3c742a9bbabe43b1ce40d
Domagoj Kriskovic 3 лет назад
Родитель
Сommit
a05c201652

+ 23 - 9
services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx

@@ -21,6 +21,7 @@ import {
 import { ensureEmptyLine } from '../../extensions/toolbar/commands'
 import { useTranslation } from 'react-i18next'
 import useEventListener from '../../../../shared/hooks/use-event-listener'
+import { prepareLines } from '../../utils/prepare-lines'
 
 export const FigureModal = memo(function FigureModal() {
   return (
@@ -138,8 +139,8 @@ const FigureModalContent = () => {
       dispatch({ error: String(error) })
       return
     }
-    const labelCommand = includeLabel ? '\n\\label{fig:enter-label}' : ''
-    const captionCommand = includeCaption ? '\n\\caption{Enter Caption}' : ''
+    const labelCommand = includeLabel ? '\\label{fig:enter-label}' : ''
+    const captionCommand = includeCaption ? '\\caption{Enter Caption}' : ''
 
     if (figure) {
       // Updating existing figure
@@ -150,14 +151,19 @@ const FigureModalContent = () => {
         // We should insert a caption
         changes.push({
           from: figure.graphicsCommand.to,
-          insert: captionCommand,
+          insert: prepareLines(
+            ['', captionCommand],
+            view.state,
+            figure.graphicsCommand.to
+          ),
         })
       }
       if (!hadLabelBefore && includeLabel) {
+        const from = figure.caption?.to ?? figure.graphicsCommand.to
         // We should insert a label
         changes.push({
-          from: figure.caption?.to ?? figure.graphicsCommand.to,
-          insert: labelCommand,
+          from,
+          insert: prepareLines(['', labelCommand], view.state, from),
         })
       }
       if (hadCaptionBefore && !includeCaption) {
@@ -203,11 +209,19 @@ const FigureModalContent = () => {
           const { pos, suffix } = ensureEmptyLine(view.state, range)
           const widthArgument =
             width !== undefined ? `[width=${width}\\linewidth]` : ''
-          const graphicxCommand = `\\includegraphics${widthArgument}{${path}}`
           const changes: ChangeSpec = view.state.changes({
-            insert: `\\begin{figure}\n\\centering\n${graphicxCommand}${captionCommand}${labelCommand}${
-              labelCommand || captionCommand ? '\n' : '' // Add an extra newline if we've added a caption or label
-            }\\end{figure}${suffix}`,
+            insert: prepareLines(
+              [
+                '\\begin{figure}',
+                '\t\\centering',
+                `\t\\includegraphics${widthArgument}{${path}}`,
+                `\t${captionCommand}` || null,
+                `\t${labelCommand}` || null,
+                `\\end{figure}${suffix}`,
+              ],
+              view.state,
+              pos
+            ),
             from: pos,
           })
 

+ 2 - 1
services/web/frontend/js/features/source-editor/extensions/toolbar/commands.ts

@@ -33,7 +33,8 @@ export const ensureEmptyLine = (state: EditorState, range: SelectionRange) => {
   let suffix = ''
 
   const line = state.doc.lineAt(pos)
-  if (line.length) {
+
+  if (line.text.trim().length) {
     pos = Math.min(line.to + 1, state.doc.length)
     const nextLine = state.doc.lineAt(pos)
 

+ 33 - 0
services/web/frontend/js/features/source-editor/utils/prepare-lines.ts

@@ -0,0 +1,33 @@
+/**
+ * Adapted from CodeMirror 6 (@codemirror/autocomplete), licensed under the MIT license:
+ * https://github.com/codemirror/autocomplete/blob/08f63add9f470a032d3802a4599caa86c75de5cb/src/snippet.ts#L29-L45
+ */
+
+import { indentUnit } from '@codemirror/language'
+import { EditorState } from '@codemirror/state'
+
+// apply correct indentation to passed lines
+export function prepareLines(
+  lines: (string | null)[],
+  state: EditorState,
+  pos: number
+) {
+  const text = []
+  const lineStart = [pos]
+  const lineObj = state.doc.lineAt(pos)
+  const baseIndent = /^\s*/.exec(lineObj.text)![0]
+  for (let line of lines) {
+    if (line === null) continue
+    if (text.length) {
+      let indent = baseIndent
+      const tabs = /^\t*/.exec(line)![0].length
+      for (let i = 0; i < tabs; i++) indent += state.facet(indentUnit)
+      lineStart.push(pos + indent.length - tabs)
+      line = indent + line.slice(tabs)
+    }
+    text.push(line)
+    pos += line.length + 1
+  }
+
+  return text.join('\n')
+}

+ 5 - 5
services/web/test/frontend/features/source-editor/components/figure-modal.spec.tsx

@@ -94,7 +94,7 @@ describe('<FigureModal />', function () {
 
       cy.get('.cm-content').should(
         'have.text',
-        '\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
+        '\\begin{figure}    \\centering    Enter Caption    🏷fig:enter-label\\end{figure}'
       )
     })
 
@@ -140,7 +140,7 @@ describe('<FigureModal />', function () {
       cy.findByText('Insert figure').click()
       cy.get('.cm-content').should(
         'have.text',
-        '\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
+        '\\begin{figure}    \\centering    Enter Caption    🏷fig:enter-label\\end{figure}'
       )
     })
   })
@@ -214,7 +214,7 @@ describe('<FigureModal />', function () {
 
       cy.get('.cm-content').should(
         'have.text',
-        '\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
+        '\\begin{figure}    \\centering    Enter Caption    🏷fig:enter-label\\end{figure}'
       )
     })
 
@@ -242,7 +242,7 @@ describe('<FigureModal />', function () {
 
       cy.get('.cm-content').should(
         'have.text',
-        '\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
+        '\\begin{figure}    \\centering    Enter Caption    🏷fig:enter-label\\end{figure}'
       )
     })
   })
@@ -292,7 +292,7 @@ describe('<FigureModal />', function () {
 
       cy.get('.cm-content').should(
         'have.text',
-        '\\begin{figure}\\centeringEnter Caption🏷fig:enter-label\\end{figure}'
+        '\\begin{figure}    \\centering    Enter Caption    🏷fig:enter-label\\end{figure}'
       )
     })
   })