Skip to content

Commit 8287980

Browse files
authored
Merge pull request #982 from GetStream/mads/md-list-numbering
2 parents 9b25d98 + 3cc0cf7 commit 8287980

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

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

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { GestureResponderEvent, Linking, Text } from 'react-native';
2+
import { GestureResponderEvent, Linking, Text, View } from 'react-native';
33
import anchorme from 'anchorme';
44
import truncate from 'lodash/truncate';
55
// @ts-expect-error
@@ -11,6 +11,7 @@ import {
1111
ParseFunction,
1212
parseInline,
1313
ReactNodeOutput,
14+
SingleASTNode,
1415
} from 'simple-markdown';
1516

1617
import type { MessageType } from '../../../MessageList/hooks/useMessageList';
@@ -38,9 +39,15 @@ const defaultMarkdownStyles: MarkdownStyle = {
3839
marginBottom: 8,
3940
marginTop: 8,
4041
},
42+
listItemNumber: {
43+
fontWeight: 'bold',
44+
},
4145
listItemText: {
4246
flex: 0,
4347
},
48+
listRow: {
49+
flexDirection: 'row',
50+
},
4451
mentions: {
4552
fontWeight: '700',
4653
},
@@ -234,10 +241,54 @@ export const renderText = <
234241
);
235242
};
236243

244+
const listLevels = {
245+
sub: 'sub',
246+
top: 'top',
247+
};
248+
249+
/**
250+
* For lists and sublists, the default behavior of the markdown library we use is
251+
* to always renumber any list, so all ordered lists start from 1.
252+
*
253+
* This custom rule overrides this behavior both for top level lists and sublists,
254+
* in order to start the numbering from the number of the first list item provided.
255+
* */
256+
const customListAtLevel =
257+
(level: keyof typeof listLevels): ReactNodeOutput =>
258+
(node, output, { ...state }) => {
259+
const items = node.items.map((item: Array<SingleASTNode>, index: number) => {
260+
const withinList = item.length > 1 && item[1].type === 'list';
261+
const content = output(item, { ...state, withinList });
262+
263+
const isTopLevelText =
264+
['text', 'paragraph', 'strong'].includes(item[0].type) && withinList === false;
265+
266+
return (
267+
<View key={index} style={styles.listRow}>
268+
<Text style={styles.listItemNumber}>
269+
{node.ordered ? `${node.start + index}. ` : `\u2022`}
270+
</Text>
271+
<Text style={[styles.listItemText, isTopLevelText && { marginBottom: 0 }]}>
272+
{content}
273+
</Text>
274+
</View>
275+
);
276+
});
277+
278+
const isSublist = level === 'sub';
279+
return (
280+
<View key={state.key} style={[isSublist ? styles.list : styles.sublist]}>
281+
{items}
282+
</View>
283+
);
284+
};
285+
237286
const customRules = {
238287
link: { react },
288+
list: { react: customListAtLevel('top') },
239289
// we have no react rendering support for reflinks
240290
reflink: { match: () => null },
291+
sublist: { react: customListAtLevel('sub') },
241292
...(mentionedUsers
242293
? {
243294
mentions: {

0 commit comments

Comments
 (0)