Docs
🎨 ⏐ Customization
Markdown Plugins

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:

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:

InputOutput
CVE-2021-44228CVE-2021-44228 (opens in a new tab)
CVE-2021-34527CVE-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:

MatcherExample
SSN123-45-6789
Credit Card4532-1234-5678-9010
Bitcoin1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa

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 the g flag)
  • validate — Optional function that receives the matched value; return true to redact, false to 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-45046

We 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 blocks
  • a - Links
  • img - Images
  • table / thead / tbody / tr / td / th - Tables
  • h1 through h6 - Headings
  • p - Paragraphs
  • ul / 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).