Markdown Plugins
reachat uses remark (opens in a new tab) to parse and render markdown.
You can use the remarkPlugins prop to add custom plugins to the markdown parser.
Any plugin that is supported by remark should work here as well.
Pre-packaged plugins
Out of the box, we provide several plugins:
- CVE Plugin (opens in a new tab) - Automatically link CVE identifiers
- Redact Plugin (opens in a new tab) - Mask sensitive data (SSNs, credit cards, etc.)
You can view the Storybook Stories (opens in a new tab) for more examples.
CVE Plugin
The remarkCve plugin automatically detects
CVE identifiers (opens in a new tab) in chat messages and converts them into
clickable links to the MITRE CVE database.
Usage
import { Chat, remarkCve } from 'reachat';
<Chat remarkPlugins={[remarkCve]}>
<SessionMessages />
<ChatInput />
</Chat>What It Does
Any text matching the pattern CVE-YYYY-NNNNN (e.g., CVE-2021-44228) is
automatically replaced with a link to its MITRE entry:
| Input | Output |
|---|---|
CVE-2021-44228 | CVE-2021-44228 (opens in a new tab) |
CVE-2021-34527 | CVE-2021-34527 (opens in a new tab) |
The plugin matches identifiers with years in the 1900–2099 range and 4–7 digit sequence numbers, covering the full CVE numbering scheme.
Redact Plugin
The remarkRedact plugin automatically detects and masks sensitive data in chat messages
using pattern-based matchers. It integrates with the reablocks Redact component (opens in a new tab)
to provide a toggleable redaction UI where users can reveal masked content on click.
Quick Start
reachat exports remarkRedact and a set of commonRedactMatchers that cover
SSNs, credit card numbers, and Bitcoin addresses out of the box:
import { Chat, remarkRedact, commonRedactMatchers } from 'reachat';
<Chat
remarkPlugins={[remarkRedact(commonRedactMatchers)]}
>
<SessionMessages />
<ChatInput />
</Chat>Any matching text in chat messages will be automatically replaced with a redacted UI element.
Common Matchers
The built-in commonRedactMatchers includes:
| Matcher | Example |
|---|---|
| SSN | 123-45-6789 |
| Credit Card | 4532-1234-5678-9010 |
| Bitcoin | 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa |
Custom Matchers
You can define your own matchers by providing a name, a pattern (RegExp),
and an optional validate function:
import { Chat, remarkRedact, commonRedactMatchers } from 'reachat';
const customMatchers = [
{
name: 'Email',
pattern: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g
},
{
name: 'Phone',
pattern: /\b\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g
},
{
name: 'Secret Code',
pattern: /\bSECRET-\d+\b/g,
validate: (match) => match.length > 8
},
...commonRedactMatchers
];
<Chat remarkPlugins={[remarkRedact(customMatchers)]}>
<SessionMessages />
<ChatInput />
</Chat>RedactMatcher Interface
interface RedactMatcher {
name: string;
pattern: RegExp;
validate?: (match: string) => boolean;
}name— Label for the matcher (e.g., "SSN", "Email")pattern— Regular expression to match sensitive data (use thegflag)validate— Optional function that receives the matched value; returntrueto redact,falseto skip
Writing your own plugin
We will build a plugin that will identify and render CVE links. Below is a sample response:
Please review the following CVEs:
- CVE-2021-34527
- CVE-2021-44228
- CVE-2021-45046We can leverage the remarkPlugins prop to add custom plugins to the markdown parser. Below
is an example of the plugin code:
import { findAndReplace } from 'mdast-util-find-and-replace';
const CVE_REGEX = /(CVE-(19|20)\d{2}-\d{4,7})/gi;
export function remarkCve() {
return (tree, _file) => {
findAndReplace(tree, [[
CVE_REGEX,
replaceCve as unknown as any
]]);
};
function replaceCve(value, id) {
return [
{
type: 'link',
url: `https://cve.mitre.org/cgi-bin/cvename.cgi?name=${id}`,
children: [
{ children: [{ type: 'text', value: value.trim() }] }
]
}
];
}
}After you integrate this into your app, the above markdown will render as follows:
Please review the following CVEs:
- [CVE-2021-34527](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-34527)
- [CVE-2021-44228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228)
- [CVE-2021-45046](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45046)To leverage our new plugin, we need to include it in the remarkPlugins prop.
import { Chat } from 'reachat';
import { remarkCve } from 'PATH_YOU_SAVED_THE_PLUGIN';
export function App() {
return (
<Chat remarkPlugins={[remarkCve]}>
...rest of your code...
</Chat>
);
}Custom Markdown Components
You can customize how specific markdown elements are rendered using the markdownComponents prop. This is useful for overriding the default rendering of code blocks or other markdown elements.
If you're using the Component Catalog, its remark plugin and
component overrides are applied automatically when you pass the catalog to the components prop.
For manual wiring, see the advanced usage section.
Basic Usage
import { Chat } from 'reachat';
<Chat
markdownComponents={{
code: ({ node, inline, className, children, ...props }) => {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighter
language={match[1]}
PreTag="div"
{...props}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>
{children}
</code>
);
}
}}
>
{/* ... */}
</Chat>Available Component Overrides
You can override any standard markdown element:
code/pre- Code blocksa- Linksimg- Imagestable/thead/tbody/tr/td/th- Tablesh1throughh6- Headingsp- Paragraphsul/ol/li- Lists- And many more standard markdown elements
For a complete list of available overrides, see the react-markdown components documentation (opens in a new tab).