diff --git a/services/web/frontend/js/features/source-editor/extensions/math-preview.ts b/services/web/frontend/js/features/source-editor/extensions/math-preview.ts index cce06f0fe1..831a8ab8ad 100644 --- a/services/web/frontend/js/features/source-editor/extensions/math-preview.ts +++ b/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') diff --git a/services/web/frontend/js/features/source-editor/utils/tree-operations/math.ts b/services/web/frontend/js/features/source-editor/utils/tree-operations/math.ts index 5fa7e4a4ce..c4760c8d68 100644 --- a/services/web/frontend/js/features/source-editor/utils/tree-operations/math.ts +++ b/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 } }