Skip to content

Commit 5275e9c

Browse files
committed
feat: add markdown parsing fixes, optimistic code capture and various improvements
1 parent 01e116c commit 5275e9c

File tree

3 files changed

+32
-29
lines changed

3 files changed

+32
-29
lines changed

package/src/components/Message/MessageSimple/utils/generateMarkdownText.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,21 @@ export const generateMarkdownText = (text?: string) => {
3333
resultText = resultText.replace(mentionsRegex, `@${displayLink}`);
3434
}
3535

36-
// FIXME: Should not happen within codeblocks.
37-
resultText = resultText.replace(/[<"'>]/g, '\\$&');
36+
// Escape the " and ' characters, except in code blocks where we deem this allowed.
37+
resultText = resultText.replace(/(```[\s\S]*?```|`.*?`)|[<"'>]/g, (match, code) => {
38+
if (code) return code;
39+
return `\\${match}`;
40+
});
3841

3942
// Remove whitespaces that come directly after newlines except in code blocks where we deem this allowed.
4043
resultText = resultText.replace(/(```[\s\S]*?```|`.*?`)|\n[ ]{2,}/g, (_, code) => {
4144
if (code) return code;
4245
return '\n';
4346
});
4447

48+
// Always replace \n``` with \n\n``` to force the markdown state machine to treat it as a separate block. Otherwise, code blocks inside of list
49+
// items for example were broken. We clean up the code block closing state within the rendering itself.
50+
resultText = resultText.replace(/\n```/g, '\n\n```');
51+
4552
return resultText;
4653
};

package/src/components/Message/MessageSimple/utils/renderText.tsx

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const defaultMarkdownStyles: MarkdownStyle = {
9191
backgroundColor: '#DDDDDD',
9292
fontFamily: Platform.OS === 'ios' ? 'Courier' : 'Monospace',
9393
fontWeight: '500',
94+
marginVertical: 8,
9495
},
9596
inlineCode: {
9697
fontSize: 13,
@@ -129,28 +130,25 @@ const defaultMarkdownStyles: MarkdownStyle = {
129130
borderColor: '#222222',
130131
borderRadius: 3,
131132
borderWidth: 1,
133+
flex: 1,
134+
flexDirection: 'row',
132135
},
133136
tableHeader: {
134137
backgroundColor: '#222222',
135-
flex: 1,
138+
flexDirection: 'row',
136139
justifyContent: 'space-around',
137140
},
138141
tableHeaderCell: {
139142
color: '#ffffff',
140-
fontWeight: 'bold',
141-
padding: 5,
143+
fontWeight: '500',
142144
},
143145
tableRow: {
144-
//borderBottomWidth: 1,
146+
alignItems: 'center',
145147
borderColor: '#222222',
146-
flexDirection: 'row',
147148
justifyContent: 'space-around',
148149
},
149150
tableRowCell: {
150-
padding: 5,
151-
},
152-
tableRowLast: {
153-
borderColor: 'transparent',
151+
flex: 1,
154152
},
155153
};
156154

@@ -223,33 +221,30 @@ export const renderText = <
223221
...markdownStyles?.mentions,
224222
},
225223
table: {
226-
borderColor: '#222222',
227-
borderRadius: 3,
228-
borderWidth: 1,
229-
flex: 1,
230-
flexDirection: 'row',
224+
...defaultMarkdownStyles.table,
225+
marginVertical: 8,
226+
...markdownStyles?.table,
231227
},
232228
tableHeader: {
233-
backgroundColor: '#222222',
234-
flexDirection: 'row',
235-
justifyContent: 'space-around',
229+
...defaultMarkdownStyles.tableHeader,
230+
...markdownStyles?.tableHeader,
236231
},
237232
tableHeaderCell: {
238-
color: '#ffffff',
239-
fontWeight: 'bold',
233+
...defaultMarkdownStyles.tableHeaderCell,
240234
padding: 5,
235+
...markdownStyles?.tableHeaderCell,
241236
},
242237
tableRow: {
243-
alignItems: 'center',
244-
borderColor: '#222222',
245-
justifyContent: 'space-around',
238+
...defaultMarkdownStyles.tableRow,
239+
...markdownStyles?.tableRow,
246240
},
247241
tableRowCell: {
248-
flex: 1,
242+
...defaultMarkdownStyles.tableRowCell,
249243
padding: 5,
244+
...markdownStyles?.tableRowCell,
250245
},
251246
tableRowLast: {
252-
borderColor: 'transparent',
247+
...markdownStyles?.tableRowLast,
253248
},
254249
text: {
255250
...defaultMarkdownStyles.text,
@@ -391,7 +386,7 @@ export const renderText = <
391386

392387
const codeBlockReact: ReactNodeOutput = (node, _, state) => (
393388
<ReactiveScrollView key={state.key}>
394-
<Text style={styles.codeBlock}>{node.content}</Text>
389+
<Text style={styles.codeBlock}>{node?.content?.trim()}</Text>
395390
</ReactiveScrollView>
396391
);
397392

@@ -558,7 +553,6 @@ const MarkdownTableColumn = ({ items, output, state, styles }: MarkdownTableRowP
558553

559554
const ColumnCell = useCallback(
560555
({ content }: { content: SingleASTNode }) =>
561-
// console.log('CONTENT: ', content);
562556
content ? (
563557
<View style={styles.tableRow}>
564558
<View style={styles.tableRowCell}>{output(content, state)}</View>

package/src/components/Message/hooks/useStreamingMessage.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export const useStreamingMessage = <
3232
const newCursorValue = textCursor.current + renderingLetterCount;
3333
const newText = text.substring(0, newCursorValue);
3434
textCursor.current += newText.length - textCursor.current;
35-
setStreamedMessageText(newText);
35+
const codeBlockCounts = (newText.match(/```/g) || []).length;
36+
const shouldOptimisticallyCloseCodeBlock = codeBlockCounts > 0 && codeBlockCounts % 2 > 0;
37+
setStreamedMessageText(shouldOptimisticallyCloseCodeBlock ? newText + '```' : newText);
3638
}, letterInterval);
3739

3840
return () => {

0 commit comments

Comments
 (0)