@@ -18,6 +18,7 @@ import { getHistory, isPreviousSiblingCodeBlock } from "./history";
1818import InsertBar from "./insert-bar" ;
1919import { useFileContext } from "@cocalc/frontend/lib/file-context" ;
2020import { isEqual } from "lodash" ;
21+ import Mermaid from "./mermaid" ;
2122
2223function Element ( { attributes, children, element } : RenderElementProps ) {
2324 if ( element . type != "code_block" ) {
@@ -29,9 +30,7 @@ function Element({ attributes, children, element }: RenderElementProps) {
2930 const [ info , setInfo ] = useState < string > ( element . info ?? "" ) ;
3031 const infoFocusedRef = useRef < boolean > ( false ) ;
3132 const [ output , setOutput ] = useState < null | ReactNode > ( null ) ;
32-
3333 const runRef = useRef < RunFunction | null > ( null ) ;
34-
3534 const setElement = useSetElement ( editor , element ) ;
3635 // textIndent: 0 is needed due to task lists -- see https://github.com/sagemathinc/cocalc/issues/6074
3736 const { change } = useChange ( ) ;
@@ -64,108 +63,115 @@ function Element({ attributes, children, element }: RenderElementProps) {
6463 above = { true }
6564 />
6665 ) }
67- < SlateCodeMirror
68- options = { { lineWrapping : true } }
69- value = { element . value }
70- info = { infoToMode ( element . info , { value : element . value } ) }
71- onChange = { ( value ) => {
72- setElement ( { value } ) ;
73- } }
74- onFocus = { async ( ) => {
75- await delay ( 1 ) ; // must be a little longer than the onBlur below.
76- if ( ! isMountedRef . current ) return ;
77- } }
78- onBlur = { async ( ) => {
79- await delay ( 0 ) ;
80- if ( ! isMountedRef . current ) return ;
81- } }
82- onShiftEnter = { ( ) => {
83- runRef . current ?.( ) ;
84- } }
85- addonBefore = {
86- < div
87- style = { {
88- borderBottom : "1px solid #ccc" ,
89- padding : "3px" ,
90- display : "flex" ,
91- background : "#f8f8f8" ,
66+ < div style = { { display : "flex" , flexDirection : "column" } } >
67+ < div style = { { flex : 1 } } >
68+ < SlateCodeMirror
69+ options = { { lineWrapping : true } }
70+ value = { element . value }
71+ info = { infoToMode ( element . info , { value : element . value } ) }
72+ onChange = { ( value ) => {
73+ setElement ( { value } ) ;
9274 } }
93- >
94- < div style = { { flex : 1 } } > </ div >
95- { element . fence && (
96- < Input
97- size = "small"
98- onKeyDown = { ( e ) => {
99- if ( e . keyCode == 13 && e . shiftKey ) {
100- runRef . current ?.( ) ;
101- } else if ( e . keyCode == 40 ) {
102- // down arrow and 38 is up. TODO
103- }
104- } }
75+ onFocus = { async ( ) => {
76+ await delay ( 1 ) ; // must be a little longer than the onBlur below.
77+ if ( ! isMountedRef . current ) return ;
78+ } }
79+ onBlur = { async ( ) => {
80+ await delay ( 0 ) ;
81+ if ( ! isMountedRef . current ) return ;
82+ } }
83+ onShiftEnter = { ( ) => {
84+ runRef . current ?.( ) ;
85+ } }
86+ addonBefore = {
87+ < div
10588 style = { {
106- flex : 1 ,
107- color : "#666" ,
108- minWidth : "100px" ,
109- maxWidth : "300px" ,
110- margin : "0 5px" ,
89+ borderBottom : "1px solid #ccc" ,
90+ padding : "3px" ,
91+ display : "flex" ,
92+ background : "#f8f8f8" ,
11193 } }
112- placeholder = "Info string (py, r, jl, tex, md, etc.)..."
113- value = { info }
114- onFocus = { ( ) => {
115- infoFocusedRef . current = true ;
116- editor . setIgnoreSelection ( true ) ;
117- } }
118- onBlur = { ( ) => {
119- infoFocusedRef . current = false ;
120- editor . setIgnoreSelection ( false ) ;
121- } }
122- onChange = { ( e ) => {
123- const info = e . target . value ;
124- setInfo ( info ) ;
125- setElement ( { info } ) ;
126- } }
127- />
128- ) }
129- { ! disableMarkdownCodebar && (
130- < ActionButtons
131- auto
132- size = "small"
133- input = { element . value }
134- history = { history }
135- setOutput = { setOutput }
136- output = { output }
137- info = { info }
138- runRef = { runRef }
139- setInfo = { ( info ) => {
140- setElement ( { info } ) ;
141- } }
142- />
143- ) }
144- </ div >
145- }
146- addonAfter = {
147- disableMarkdownCodebar || output == null ? null : (
148- < div
149- onMouseDown = { ( ) => {
150- editor . setIgnoreSelection ( true ) ;
151- } }
152- onMouseUp = { ( ) => {
153- // Re-enable slate listing for selection changes again in next render loop.
154- setTimeout ( ( ) => {
155- editor . setIgnoreSelection ( false ) ;
156- } , 0 ) ;
157- } }
158- style = { {
159- borderTop : "1px dashed #ccc" ,
160- background : "white" ,
161- padding : "5px 0 5px 30px" ,
162- } }
163- >
164- { output }
165- </ div >
166- )
167- }
168- />
94+ >
95+ < div style = { { flex : 1 } } > </ div >
96+ { element . fence && (
97+ < Input
98+ size = "small"
99+ onKeyDown = { ( e ) => {
100+ if ( e . keyCode == 13 && e . shiftKey ) {
101+ runRef . current ?.( ) ;
102+ } else if ( e . keyCode == 40 ) {
103+ // down arrow and 38 is up. TODO
104+ }
105+ } }
106+ style = { {
107+ flex : 1 ,
108+ color : "#666" ,
109+ minWidth : "100px" ,
110+ maxWidth : "300px" ,
111+ margin : "0 5px" ,
112+ } }
113+ placeholder = "Info string (py, r, jl, tex, md, etc.)..."
114+ value = { info }
115+ onFocus = { ( ) => {
116+ infoFocusedRef . current = true ;
117+ editor . setIgnoreSelection ( true ) ;
118+ } }
119+ onBlur = { ( ) => {
120+ infoFocusedRef . current = false ;
121+ editor . setIgnoreSelection ( false ) ;
122+ } }
123+ onChange = { ( e ) => {
124+ const info = e . target . value ;
125+ setInfo ( info ) ;
126+ setElement ( { info } ) ;
127+ } }
128+ />
129+ ) }
130+ { ! disableMarkdownCodebar && (
131+ < ActionButtons
132+ auto
133+ size = "small"
134+ input = { element . value }
135+ history = { history }
136+ setOutput = { setOutput }
137+ output = { output }
138+ info = { info }
139+ runRef = { runRef }
140+ setInfo = { ( info ) => {
141+ setElement ( { info } ) ;
142+ } }
143+ />
144+ ) }
145+ </ div >
146+ }
147+ addonAfter = {
148+ disableMarkdownCodebar || output == null ? null : (
149+ < div
150+ onMouseDown = { ( ) => {
151+ editor . setIgnoreSelection ( true ) ;
152+ } }
153+ onMouseUp = { ( ) => {
154+ // Re-enable slate listing for selection changes again in next render loop.
155+ setTimeout ( ( ) => {
156+ editor . setIgnoreSelection ( false ) ;
157+ } , 0 ) ;
158+ } }
159+ style = { {
160+ borderTop : "1px dashed #ccc" ,
161+ background : "white" ,
162+ padding : "5px 0 5px 30px" ,
163+ } }
164+ >
165+ { output }
166+ </ div >
167+ )
168+ }
169+ />
170+ </ div >
171+ { element . info == "mermaid" && (
172+ < Mermaid style = { { flex : 1 } } value = { element . value } />
173+ ) }
174+ </ div >
169175 < InsertBar
170176 editor = { editor }
171177 element = { element }
0 commit comments