@@ -4,29 +4,42 @@ import type {Node} from 'prosemirror-model';
44import { keydownHandler } from 'prosemirror-keymap' ;
55import { Decoration , DecorationSet , NodeView } from 'prosemirror-view' ;
66import { isTextSelection } from '../../../utils/selection' ;
7+ import type { ReactRenderer , RendererItem } from '../../../extensions/behavior/ReactRenderer' ;
78import { moveCursorToEndOfMathInline } from './commands' ;
89import { CLASSNAMES , MathNode } from './const' ;
10+ import { b , renderMathHint } from './hint' ;
911
1012import 'katex/dist/katex.min.css' ;
1113import './view-and-edit.scss' ;
1214
1315export abstract class MathNodeView implements NodeView {
1416 dom : HTMLElement ;
1517 contentDOM : HTMLElement ;
18+
1619 protected node : Node ;
1720 protected texContent : string ;
1821 protected mathViewDOM : HTMLElement ;
22+ protected mathHintContainerDOM : HTMLElement ;
23+
24+ protected hintRendererItem : RendererItem ;
25+ protected readonly reactRenderer : ReactRenderer ;
1926
20- abstract createDOM ( ) : Record < 'dom' | 'contentDOM' | 'mathViewDOM' , HTMLElement > ;
27+ abstract createDOM ( ) : Record <
28+ 'dom' | 'contentDOM' | 'mathViewDOM' | 'mathHintContainerDOM' ,
29+ HTMLElement
30+ > & { hintRendererItem : RendererItem } ;
2131 abstract isDisplayMode ( ) : boolean ;
2232
23- constructor ( node : Node ) {
33+ constructor ( node : Node , reactRenderer : ReactRenderer ) {
2434 this . node = node ;
35+ this . reactRenderer = reactRenderer ;
2536 this . texContent = this . getTexContent ( ) ;
2637 const elems = this . createDOM ( ) ;
2738 this . dom = elems . dom ;
2839 this . contentDOM = elems . contentDOM ;
2940 this . mathViewDOM = elems . mathViewDOM ;
41+ this . mathHintContainerDOM = elems . mathHintContainerDOM ;
42+ this . hintRendererItem = elems . hintRendererItem ;
3043 this . renderKatex ( ) ;
3144 }
3245
@@ -41,6 +54,14 @@ export abstract class MathNodeView implements NodeView {
4154 return true ;
4255 }
4356
57+ ignoreMutation ( mutation : MutationRecord ) : boolean {
58+ return mutation . type === 'childList' && mutation . target === this . mathHintContainerDOM ;
59+ }
60+
61+ destroy ( ) {
62+ this . hintRendererItem . remove ( ) ;
63+ }
64+
4465 protected renderKatex ( ) {
4566 try {
4667 katex . render ( this . texContent , this . mathViewDOM , {
@@ -62,11 +83,15 @@ export abstract class MathNodeView implements NodeView {
6283}
6384
6485export class MathInlineNodeView extends MathNodeView {
86+ destroy ( ) {
87+ this . hintRendererItem ?. remove ( ) ;
88+ }
89+
6590 isDisplayMode ( ) : boolean {
6691 return false ;
6792 }
6893
69- createDOM ( ) : Record < 'dom' | 'contentDOM' | 'mathViewDOM' , HTMLElement > {
94+ createDOM ( ) {
7095 const dom = document . createElement ( 'span' ) ;
7196 dom . classList . add ( 'math-container' , 'math-inline-container' ) ;
7297
@@ -76,10 +101,25 @@ export class MathInlineNodeView extends MathNodeView {
76101
77102 const mathInlineDOM = this . createMathInlineDOM ( ) ;
78103
104+ const mathHintContainerDOM = document . createElement ( 'div' ) ;
105+ mathHintContainerDOM . contentEditable = 'false' ;
106+ mathHintContainerDOM . classList . add ( b ( 'inline-view' ) ) ;
107+
79108 dom . appendChild ( mathViewDOM ) ;
80109 dom . appendChild ( mathInlineDOM . container ) ;
81-
82- return { dom, contentDOM : mathInlineDOM . content , mathViewDOM} ;
110+ dom . appendChild ( mathHintContainerDOM ) ;
111+
112+ const hintRendererItem = this . reactRenderer . createItem ( 'math-inline-hint' , ( ) =>
113+ renderMathHint ( { offset : { left : 3 , top : - 1 } } , mathHintContainerDOM ) ,
114+ ) ;
115+
116+ return {
117+ dom,
118+ contentDOM : mathInlineDOM . content ,
119+ mathViewDOM,
120+ mathHintContainerDOM,
121+ hintRendererItem,
122+ } ;
83123 }
84124
85125 // same as math-inline spec toDOM()
@@ -108,7 +148,7 @@ export class MathBlockNodeView extends MathNodeView {
108148 return true ;
109149 }
110150
111- createDOM ( ) : Record < 'dom' | 'contentDOM' | 'mathViewDOM' , HTMLElement > {
151+ createDOM ( ) {
112152 const dom = document . createElement ( 'div' ) ;
113153 dom . classList . add ( 'math-container' , 'math-block-container' ) ;
114154
@@ -119,19 +159,28 @@ export class MathBlockNodeView extends MathNodeView {
119159 const contentDOM = document . createElement ( 'div' ) ;
120160 contentDOM . classList . add ( 'math-block' ) ;
121161
162+ const mathHintContainerDOM = document . createElement ( 'div' ) ;
163+ mathHintContainerDOM . contentEditable = 'false' ;
164+ mathHintContainerDOM . classList . add ( b ( 'block-view' ) ) ;
165+
166+ dom . appendChild ( mathHintContainerDOM ) ;
122167 dom . appendChild ( mathViewDOM ) ;
123168 dom . appendChild ( contentDOM ) ;
124169
125- return { dom, contentDOM, mathViewDOM} ;
170+ const hintRendererItem = this . reactRenderer . createItem ( 'math-block-hint' , ( ) =>
171+ renderMathHint ( { offset : { left : - 3 } } , mathHintContainerDOM ) ,
172+ ) ;
173+
174+ return { dom, contentDOM, mathViewDOM, mathHintContainerDOM, hintRendererItem} ;
126175 }
127176}
128177
129- export const mathViewAndEditPlugin = ( ) =>
178+ export const mathViewAndEditPlugin = ( { reactRenderer } : { reactRenderer : ReactRenderer } ) =>
130179 new Plugin ( {
131180 props : {
132181 nodeViews : {
133- [ MathNode . Block ] : ( node ) => new MathBlockNodeView ( node ) ,
134- [ MathNode . Inline ] : ( node ) => new MathInlineNodeView ( node ) ,
182+ [ MathNode . Block ] : ( node ) => new MathBlockNodeView ( node , reactRenderer ) ,
183+ [ MathNode . Inline ] : ( node ) => new MathInlineNodeView ( node , reactRenderer ) ,
135184 } ,
136185 handleKeyDown : keydownHandler ( {
137186 ArrowLeft : moveCursorToEndOfMathInline ,
0 commit comments