@@ -11,6 +11,7 @@ import {
11
11
} from '@typebot.io/schemas'
12
12
import {
13
13
isBubbleBlock ,
14
+ isEmpty ,
14
15
isInputBlock ,
15
16
isIntegrationBlock ,
16
17
isLogicBlock ,
@@ -26,6 +27,12 @@ import { getPrefilledInputValue } from './getPrefilledValue'
26
27
import { parseDateInput } from './blocks/inputs/date/parseDateInput'
27
28
import { deepParseVariables } from './variables/deepParseVariables'
28
29
import { parseVideoUrl } from '@typebot.io/lib/parseVideoUrl'
30
+ import { TDescendant , createPlateEditor } from '@udecode/plate-common'
31
+ import {
32
+ createDeserializeMdPlugin ,
33
+ deserializeMd ,
34
+ } from '@udecode/plate-serializer-md'
35
+ import { getVariablesToParseInfoInText } from './variables/parseVariables'
29
36
30
37
export const executeGroup =
31
38
(
@@ -158,12 +165,19 @@ const parseBubbleBlock =
158
165
( variables : Variable [ ] ) =>
159
166
( block : BubbleBlock ) : ChatReply [ 'messages' ] [ 0 ] => {
160
167
switch ( block . type ) {
161
- case BubbleBlockType . TEXT :
162
- return deepParseVariables (
163
- variables ,
164
- { } ,
165
- { takeLatestIfList : true }
166
- ) ( block )
168
+ case BubbleBlockType . TEXT : {
169
+ return {
170
+ ...block ,
171
+ content : {
172
+ ...block . content ,
173
+ richText : parseVariablesInRichText (
174
+ block . content . richText ,
175
+ variables
176
+ ) ,
177
+ } ,
178
+ }
179
+ }
180
+
167
181
case BubbleBlockType . EMBED : {
168
182
const message = deepParseVariables ( variables ) ( block )
169
183
return {
@@ -189,6 +203,82 @@ const parseBubbleBlock =
189
203
}
190
204
}
191
205
206
+ const parseVariablesInRichText = (
207
+ elements : TDescendant [ ] ,
208
+ variables : Variable [ ]
209
+ ) : TDescendant [ ] => {
210
+ const parsedElements : TDescendant [ ] = [ ]
211
+ for ( const element of elements ) {
212
+ if ( 'text' in element ) {
213
+ const text = element . text as string
214
+ if ( isEmpty ( text ) ) {
215
+ parsedElements . push ( element )
216
+ continue
217
+ }
218
+ const variablesInText = getVariablesToParseInfoInText ( text , variables )
219
+ if ( variablesInText . length === 0 ) {
220
+ parsedElements . push ( element )
221
+ continue
222
+ }
223
+ for ( const variableInText of variablesInText ) {
224
+ const textBeforeVariable = text . substring ( 0 , variableInText . startIndex )
225
+ const textAfterVariable = text . substring ( variableInText . endIndex )
226
+ const isStandaloneElement =
227
+ isEmpty ( textBeforeVariable ) && isEmpty ( textAfterVariable )
228
+ const variableElements = convertMarkdownToRichText (
229
+ isStandaloneElement
230
+ ? variableInText . value
231
+ : variableInText . value . replace ( / [ \n ] + / g, ' ' )
232
+ )
233
+ if ( isStandaloneElement ) {
234
+ parsedElements . push ( ...variableElements )
235
+ continue
236
+ }
237
+ const children : TDescendant [ ] = [ ]
238
+ if ( isNotEmpty ( textBeforeVariable ) )
239
+ children . push ( {
240
+ text : textBeforeVariable ,
241
+ } )
242
+ children . push ( {
243
+ type : 'inline-variable' ,
244
+ children : variableElements ,
245
+ } )
246
+ if ( isNotEmpty ( textAfterVariable ) )
247
+ children . push ( {
248
+ ...element ,
249
+ text : textAfterVariable ,
250
+ } )
251
+ parsedElements . push ( ...children )
252
+ }
253
+ continue
254
+ }
255
+
256
+ const type =
257
+ element . children . length === 1 &&
258
+ 'text' in element . children [ 0 ] &&
259
+ ( element . children [ 0 ] . text as string ) . startsWith ( '{{' ) &&
260
+ ( element . children [ 0 ] . text as string ) . endsWith ( '}}' )
261
+ ? 'variable'
262
+ : element . type
263
+
264
+ parsedElements . push ( {
265
+ ...element ,
266
+ type,
267
+ children : parseVariablesInRichText (
268
+ element . children as TDescendant [ ] ,
269
+ variables
270
+ ) ,
271
+ } )
272
+ }
273
+ return parsedElements
274
+ }
275
+
276
+ const convertMarkdownToRichText = ( text : string ) : TDescendant [ ] => {
277
+ const plugins = [ createDeserializeMdPlugin ( ) ]
278
+ //@ts -ignore
279
+ return deserializeMd ( createPlateEditor ( { plugins } ) , text )
280
+ }
281
+
192
282
export const parseInput =
193
283
( state : SessionState ) =>
194
284
async ( block : InputBlock ) : Promise < ChatReply [ 'input' ] > => {
0 commit comments