Ver código fonte

Merge pull request #19617 from overleaf/dp-tooltip-alignment

Always render math preview tooltip at start of math content

GitOrigin-RevId: b0af7aa3c0920b2a9b9930f27a580018de1d2f52
David 2 anos atrás
pai
commit
72c7b946ed

+ 15 - 10
services/web/frontend/js/features/source-editor/extensions/math-preview.ts

@@ -14,6 +14,7 @@ import {
 import { loadMathJax } from '../../mathjax/load-mathjax'
 import { descendantsOfNodeWithType } from '../utils/tree-query'
 import {
+  MathContainer,
   mathAncestorNode,
   parseMathContainer,
 } from '../utils/tree-operations/math'
@@ -92,12 +93,13 @@ function buildTooltips(state: EditorState): readonly Tooltip[] {
 
   for (const range of state.selection.ranges) {
     if (range.empty) {
-      const pos = range.from
-      const content = buildTooltipContent(state, pos)
-      if (content) {
+      const mathContainer = getMathContainer(state, range.from)
+      const content = buildTooltipContent(state, mathContainer)
+      if (content && mathContainer) {
         const tooltip: Tooltip = {
-          pos,
+          pos: mathContainer.pos,
           above: true,
+          strictSide: true,
           arrow: false,
           create() {
             const dom = document.createElement('div')
@@ -116,18 +118,21 @@ function buildTooltips(state: EditorState): readonly Tooltip[] {
   return tooltips
 }
 
-const buildTooltipContent = (
-  state: EditorState,
-  pos: number
-): HTMLDivElement | null => {
-  // if anywhere inside Math, render the whole Math content
+const getMathContainer = (state: EditorState, pos: number) => {
+  // if anywhere inside Math, find the whole Math node
   const ancestorNode = mathAncestorNode(state, pos)
   if (!ancestorNode) return null
 
   const [node] = descendantsOfNodeWithType(ancestorNode, 'Math', 'Math')
   if (!node) return null
 
-  const math = parseMathContainer(state, node, ancestorNode)
+  return parseMathContainer(state, node, ancestorNode)
+}
+
+const buildTooltipContent = (
+  state: EditorState,
+  math: MathContainer | null
+): HTMLDivElement | null => {
   if (!math || !math.content.length) return null
 
   const element = document.createElement('div')

+ 11 - 2
services/web/frontend/js/features/source-editor/utils/tree-operations/math.ts

@@ -3,6 +3,13 @@ import { EditorState } from '@codemirror/state'
 import { SyntaxNode, SyntaxNodeRef } from '@lezer/common'
 import { ancestorNodeOfType } from './ancestors'
 
+export type MathContainer = {
+  content: string
+  displayMode: boolean
+  passToMathJax: boolean
+  pos: number
+}
+
 export const mathAncestorNode = (state: EditorState, pos: number) =>
   ancestorNodeOfType(state, pos, '$MathContainer') ||
   ancestorNodeOfType(state, pos, 'EquationEnvironment') ||
@@ -13,7 +20,7 @@ export const parseMathContainer = (
   state: EditorState,
   nodeRef: SyntaxNodeRef,
   ancestorNode: SyntaxNode
-) => {
+): MathContainer | null => {
   // the content of the Math element, without braces
   const innerContent = state.doc.sliceString(nodeRef.from, nodeRef.to).trim()
 
@@ -24,6 +31,7 @@ export const parseMathContainer = (
   let content = innerContent
   let displayMode = false
   let passToMathJax = true
+  let pos = nodeRef.from
 
   if (ancestorNode.type.is('$Environment')) {
     const environmentName = getEnvironmentName(ancestorNode, state)
@@ -37,6 +45,7 @@ export const parseMathContainer = (
         content = state.doc
           .sliceString(ancestorNode.from, ancestorNode.to)
           .trim()
+        pos = ancestorNode.from
       }
 
       if (environmentName !== 'math') {
@@ -52,5 +61,5 @@ export const parseMathContainer = (
     }
   }
 
-  return { content, displayMode, passToMathJax }
+  return { content, displayMode, passToMathJax, pos }
 }