Skip to content

Commit

Permalink
feat: expose optional remark plugin to keep all line breaks and keep …
Browse files Browse the repository at this point in the history
…HTML in message text (#2170)
  • Loading branch information
MartinCupela committed Nov 13, 2023
1 parent 8dcb1ac commit 5b191c9
Show file tree
Hide file tree
Showing 11 changed files with 935 additions and 55 deletions.
109 changes: 73 additions & 36 deletions docusaurus/docs/React/components/core-components/message-list.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -122,42 +122,6 @@ const App = () => (
);
```

#### Custom element rendering

If you feel like the default output is sufficient, but you'd like to adjust how certain [ReactMarkdown components](https://github.com/remarkjs/react-markdown#appendix-b-components) look like (like `strong` element generated by typing \*\*strong\*\*) you can do so by passing down options to a third argument of the default `renderText` function:

:::note
Types `mention` and `emoji` are special case component types generated by our SDK's custom rehype plugins.
:::

```tsx
import { renderText } from 'stream-chat-react';

const StrongComponent = ({ children }) => <b className='custom-strong-class-name'>{children}</b>;

const MentionComponent = ({ children, node: { mentionedUser } }) => (
<a data-user-id={mentionedUser.id} href={`/user-profile/${mentionedUser.id}`}>
{children}
</a>
);

const App = () => (
<Chat client={client}>
<Channel>
<Window>
<MessageList
renderText={(text, mentionedUsers) =>
renderText(text, mentionedUsers, {
customMarkDownRenderers: { strong: StrongComponent, mention: MentionComponent },
})
}
/>
</Window>
</Channel>
</Chat>
);
```

#### Custom remark and rehype plugins

If you would like to extend the array of plugins used to parse the markdown, you can provide your own lists of remark resp. rehype plugins. The logic that determines what plugins are used and in which order can be specified in custom `getRehypePlugins` and `getRemarkPlugins` functions. These receive the default array of rehype and remark plugins for further customization. Both custom functions ought to be passed to the third `renderText()` parameter. An example follows:
Expand Down Expand Up @@ -218,6 +182,79 @@ const CustomMessageList = () => (
);
```

#### Optional remark and rehype plugins

The SDK provides the following plugins that are not applied to the text parsing by the default `renderText()` implementation. However, these can be included by simply overriding the defaults with `getRemarkPlugins` and `getRehypePlugins` parameters as described in [the section about custom plugins](#custom-remark-and-rehype-plugins).

Currently, there are the following optional remark plugins available in the SDK:

- `htmlToTextPlugin` - keeps the HTML tags in the resulting text string.
- `keepLineBreaksPlugin` - replaces empty lines in text with line breaks ([according to the CommonMark Markdown specification](https://spec.commonmark.org/0.30/#hard-line-breaks), the empty lines - meaning newline characters `\n` - are not transformed to `<br/>` elements).

These can be plugged in as follows:

```tsx
import { UserResponse } from 'stream-chat';
import {
htmlToTextPlugin,
keepLineBreaksPlugin,
MessageList,
MessageListProps,
renderText,
RenderTextPluginConfigurator,
} from 'stream-chat-react';

const getRemarkPlugins: RenderTextPluginConfigurator = (plugins) => [
htmlToTextPlugin,
keepLineBreaksPlugin,
...plugins,
];

function customRenderText(text?: string, mentionedUsers?: UserResponse[]) {
return renderText(text, mentionedUsers, { getRemarkPlugins });
}

export const CustomMessageList = (props: MessageListProps) => (
<MessageList {...props} renderText={customRenderText} />
);
```

#### Custom element rendering

If you feel like the default output is sufficient, but you'd like to adjust how certain [ReactMarkdown components](https://github.com/remarkjs/react-markdown#appendix-b-components) look like (like `strong` element generated by typing \*\*strong\*\*) you can do so by passing down options to a third argument of the default `renderText` function:

:::note
Types `mention` and `emoji` are special case component types generated by our SDK's custom rehype plugins.
:::

```tsx
import { renderText } from 'stream-chat-react';

const StrongComponent = ({ children }) => <b className='custom-strong-class-name'>{children}</b>;

const MentionComponent = ({ children, node: { mentionedUser } }) => (
<a data-user-id={mentionedUser.id} href={`/user-profile/${mentionedUser.id}`}>
{children}
</a>
);

const App = () => (
<Chat client={client}>
<Channel>
<Window>
<MessageList
renderText={(text, mentionedUsers) =>
renderText(text, mentionedUsers, {
customMarkDownRenderers: { strong: StrongComponent, mention: MentionComponent },
})
}
/>
</Window>
</Channel>
</Chat>
);
```

## Props

### additionalMessageInputProps
Expand Down
Loading

0 comments on commit 5b191c9

Please sign in to comment.