1
- import React , { useState } from "react" ; // Ensure React and useState are imported
1
+ import React , { useState , useEffect } from "react" ;
2
2
import clsx from "clsx" ;
3
3
import { useThemeConfig , usePrismTheme } from "@docusaurus/theme-common" ;
4
4
import {
@@ -14,7 +14,7 @@ import WordWrapButton from "@theme/CodeBlock/WordWrapButton";
14
14
import Container from "@theme/CodeBlock/Container" ;
15
15
import type { Props as OriginalProps } from "@theme/CodeBlock" ;
16
16
17
- import { QuestDbSqlRunnerEmbedded } from '@site/src/components/QuestDbSqlRunnerEmbedded' ; // Adjust path as needed
17
+ import { QuestDbSqlRunnerEmbedded } from '@site/src/components/QuestDbSqlRunnerEmbedded' ;
18
18
19
19
import styles from "./styles.module.css" ;
20
20
@@ -59,15 +59,22 @@ export default function CodeBlockString({
59
59
const demo = parseCodeBlockDemo ( metastring ) || demoProp ;
60
60
const enableExecute = parseCodeBlockExecute ( metastring ) || executeProp ;
61
61
62
- const { lineClassNames, code } = parseLines ( children , {
62
+ const { lineClassNames, code : initialCode , tokens : initialTokens } = parseLines ( children , {
63
63
metastring,
64
64
language,
65
65
magicComments,
66
66
} ) ;
67
67
const showLineNumbers = showLineNumbersProp ?? containsLineNumbers ( metastring ) ;
68
68
69
+ const [ editableCode , setEditableCode ] = useState < string > ( initialCode ) ;
70
+ const [ isEditing , setIsEditing ] = useState < boolean > ( false ) ;
71
+
72
+ useEffect ( ( ) => {
73
+ setEditableCode ( initialCode ) ;
74
+ } , [ initialCode ] ) ;
75
+
69
76
const demoUrl = demo
70
- ? `https://demo.questdb.io/?query=${ encodeURIComponent ( code ) } &executeQuery=true`
77
+ ? `https://demo.questdb.io/?query=${ encodeURIComponent ( editableCode ) } &executeQuery=true` // Use editableCode
71
78
: null ;
72
79
73
80
const handleDemoClick = ( ) => {
@@ -78,20 +85,30 @@ export default function CodeBlockString({
78
85
79
86
const [ showExecutionResults , setShowExecutionResults ] = useState < boolean > ( false ) ;
80
87
81
- const currentQuestDbUrl = questdbUrlProp ; // If passed, use it, otherwise QuestDbSqlRunnerEmbedded will use its default.
88
+ const currentQuestDbUrl = questdbUrlProp ;
82
89
83
90
const handleExecuteToggle = ( ) => {
84
91
setShowExecutionResults ( prev => ! prev ) ;
85
92
} ;
86
93
94
+ const handleEditToggle = ( ) => {
95
+ setIsEditing ( prev => ! prev ) ;
96
+ } ;
97
+
98
+ const currentLineClassNames = isEditing
99
+ ? lineClassNames
100
+ : parseLines ( editableCode , { metastring, language, magicComments } ) . lineClassNames ;
101
+
102
+
87
103
return (
88
104
< Container
89
105
as = "div"
90
106
className = { clsx (
91
107
blockClassName ,
92
108
language &&
93
- ! blockClassName . includes ( `language-${ language } ` ) &&
94
- `language-${ language } ` ,
109
+ ! blockClassName . includes ( `language-${ language } ` ) &&
110
+ `language-${ language } ` ,
111
+ isEditing && styles . codeBlockEditing
95
112
) }
96
113
>
97
114
{ title && (
@@ -111,47 +128,77 @@ export default function CodeBlockString({
111
128
</ div >
112
129
) }
113
130
< div className = { styles . codeBlockContent } >
114
- < Highlight
115
- theme = { prismTheme }
116
- code = { code }
117
- language = { ( language ?? "text" ) as Language }
118
- >
119
- { ( { className, style, tokens, getLineProps, getTokenProps } ) => (
120
- < pre
121
- tabIndex = { 0 }
122
- ref = { wordWrap . codeBlockRef }
123
- className = { clsx ( className , styles . codeBlock , "thin-scrollbar" ) }
124
- style = { style }
125
- >
126
- < code
127
- className = { clsx (
128
- styles . codeBlockLines ,
129
- showLineNumbers && styles . codeBlockLinesWithNumbering ,
130
- ) }
131
+ { isEditing ? (
132
+ < textarea
133
+ value = { editableCode }
134
+ onChange = { ( e ) => setEditableCode ( e . target . value ) }
135
+ className = { clsx ( styles . codeBlock , styles . editableCodeArea , "thin-scrollbar" ) }
136
+ spellCheck = "false"
137
+ autoCapitalize = "off"
138
+ autoComplete = "off"
139
+ autoCorrect = "off"
140
+ rows = { Math . max ( 10 , editableCode . split ( '\n' ) . length ) }
141
+ style = { {
142
+ width : '100%' ,
143
+ fontFamily : 'var(--ifm-font-family-monospace)' ,
144
+ fontSize : 'var(--ifm-code-font-size)' ,
145
+ lineHeight : 'var(--ifm-pre-line-height)' ,
146
+ backgroundColor : prismTheme . plain . backgroundColor ,
147
+ color : prismTheme . plain . color ,
148
+ border : 'none' ,
149
+ resize : 'vertical' ,
150
+ } }
151
+ />
152
+ ) : (
153
+ < Highlight
154
+ theme = { prismTheme }
155
+ code = { editableCode } // Use editableCode
156
+ language = { ( language ?? "text" ) as Language }
157
+ >
158
+ { ( { className, style, tokens, getLineProps, getTokenProps } ) => (
159
+ < pre
160
+ tabIndex = { 0 }
161
+ ref = { wordWrap . codeBlockRef }
162
+ className = { clsx ( className , styles . codeBlock , "thin-scrollbar" ) }
163
+ style = { style }
131
164
>
132
- { tokens . map ( ( line , i ) => (
133
- < Line
134
- key = { i }
135
- line = { line }
136
- getLineProps = { getLineProps }
137
- getTokenProps = { getTokenProps }
138
- classNames = { lineClassNames [ i ] }
139
- showLineNumbers = { showLineNumbers }
140
- />
141
- ) ) }
142
- </ code >
143
- </ pre >
144
- ) }
145
- </ Highlight >
165
+ < code
166
+ className = { clsx (
167
+ styles . codeBlockLines ,
168
+ showLineNumbers && styles . codeBlockLinesWithNumbering ,
169
+ ) }
170
+ >
171
+ { tokens . map ( ( line , i ) => (
172
+ < Line
173
+ key = { i }
174
+ line = { line }
175
+ getLineProps = { getLineProps }
176
+ getTokenProps = { getTokenProps }
177
+ classNames = { currentLineClassNames [ i ] }
178
+ showLineNumbers = { showLineNumbers }
179
+ />
180
+ ) ) }
181
+ </ code >
182
+ </ pre >
183
+ ) }
184
+ </ Highlight >
185
+ ) }
146
186
< div className = { styles . buttonGroup } >
187
+ < button
188
+ onClick = { handleEditToggle }
189
+ className = { clsx ( styles . codeButton , styles . editButton ) }
190
+ title = { isEditing ? "View Code" : "Edit Code" }
191
+ >
192
+ { isEditing ? 'View Code' : 'Edit Code' }
193
+ </ button >
147
194
{ ( wordWrap . isEnabled || wordWrap . isCodeScrollable ) && (
148
195
< WordWrapButton
149
196
className = { styles . codeButton }
150
197
onClick = { ( ) => wordWrap . toggle ( ) }
151
198
isEnabled = { wordWrap . isEnabled }
152
199
/>
153
200
) }
154
- < CopyButton className = { styles . codeButton } code = { code } />
201
+ < CopyButton className = { styles . codeButton } code = { editableCode } />
155
202
{ enableExecute && (
156
203
< button
157
204
onClick = { handleExecuteToggle }
@@ -166,7 +213,7 @@ export default function CodeBlockString({
166
213
167
214
{ enableExecute && showExecutionResults && (
168
215
< QuestDbSqlRunnerEmbedded
169
- queryToExecute = { code }
216
+ queryToExecute = { editableCode }
170
217
questdbUrl = { currentQuestDbUrl }
171
218
/>
172
219
) }
0 commit comments