@@ -18,6 +18,7 @@ import { getHistory, isPreviousSiblingCodeBlock } from "./history";
18
18
import InsertBar from "./insert-bar" ;
19
19
import { useFileContext } from "@cocalc/frontend/lib/file-context" ;
20
20
import { isEqual } from "lodash" ;
21
+ import Mermaid from "./mermaid" ;
21
22
22
23
function Element ( { attributes, children, element } : RenderElementProps ) {
23
24
if ( element . type != "code_block" ) {
@@ -29,9 +30,7 @@ function Element({ attributes, children, element }: RenderElementProps) {
29
30
const [ info , setInfo ] = useState < string > ( element . info ?? "" ) ;
30
31
const infoFocusedRef = useRef < boolean > ( false ) ;
31
32
const [ output , setOutput ] = useState < null | ReactNode > ( null ) ;
32
-
33
33
const runRef = useRef < RunFunction | null > ( null ) ;
34
-
35
34
const setElement = useSetElement ( editor , element ) ;
36
35
// textIndent: 0 is needed due to task lists -- see https://github.com/sagemathinc/cocalc/issues/6074
37
36
const { change } = useChange ( ) ;
@@ -64,108 +63,115 @@ function Element({ attributes, children, element }: RenderElementProps) {
64
63
above = { true }
65
64
/>
66
65
) }
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 } ) ;
92
74
} }
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
105
88
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" ,
111
93
} }
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 >
169
175
< InsertBar
170
176
editor = { editor }
171
177
element = { element }
0 commit comments