Built-in Formatters
The Formatter Interface
All formatters extend the abstractCometChatTextFormatter class. id is its only abstract member — everything else has a working default, so the smallest useful formatter is an id plus one transform method.
Porting from v6? Read this page for the class, then Porting a v6 formatter for the members v6 had that v7 does not.
Where your formatter runs
A formatter can take part in two independent pipelines. Display is the common case; live input is opt-in.
Formatters run in
priority order (lower first), each receiving the previous one’s output.
Display members
The display pipeline never receives the message object or the logged-in user. A formatter sees text only.
Live-input members
Only relevant if your formatter drives the composer’s editable input. Display-only formatters ignore this section.v7 does not reformat the live input on keystrokes by itself. The base
onKeyUp() only forwards to your callback, and formatText() runs only on entering rich-text edit mode. To reformat as the user types, call formatText() from your own onKeyUp() override or from the callback you register.The full class
Every member of the class, annotated with who calls it and what the default does. “Called by the kit” means the UI Kit invokes it on your formatter, so overriding it takes part in the pipeline; “called by you” means nothing invokes it for you.Ids must be unique
The kit merges formatters into a map keyed byid. Two formatters with the same id leave only the last one, and reusing a built-in id — markdown-formatter, mentions-formatter, url-formatter — replaces that built-in. Plain JavaScript will run a formatter with no id, but every id-less formatter collapses onto the same key, so always declare one.
Creating a Custom Formatter
Here’s a hashtag formatter that wraps#word patterns in a styled span:
src/formatters/HashtagFormatter.ts
Registering Custom Formatters
A custom formatter is not registered on its own — it must be wrapped in a custom text plugin (see Plugins overview) and that plugin registered via the provider’splugins prop (see With Additional Plugins).
Custom formatters are registered by creating a custom text plugin that provides them:
src/plugins/CustomTextPlugin.ts
plugins prop:
Formatter Details
CometChatMarkdownFormatter
Converts markdown syntax to HTML. Runs first (priority 10) so subsequent formatters operate on HTML output.**bold**→<b>bold</b>_italic_→<i>italic</i>__underline__or++underline++→<u>underline</u>~~strikethrough~~→<s>strikethrough</s>`inline code`→<code>inline code</code>```code block```→<pre><code>code block</code></pre>> blockquote→<blockquote>blockquote</blockquote>[text](url)→<a href="url">text</a>1. item→ ordered list;• item/- item→ unordered list
CometChatMentionsFormatter
Resolves SDK mention tokens (<@uid:xxx> and <@all:label>) into styled mention chips. Requires the mentioned-users list from the message to resolve UIDs to display names.
CometChatUrlFormatter
Detects bare URLs (https://... and www.) and wraps them in clickable <a> tags with target="_blank" and rel="noopener noreferrer". Protects existing markdown links and <a> tags from double-processing.
Tips
- Priority matters — markdown must run before mentions/URLs so it doesn’t break HTML tags
- Protect code blocks — formatters should skip content inside
<code>and<pre>tags - Keep it fast — formatters run on every text message render; avoid expensive operations
- Use
shouldFormat()— override to skip formatting for specific messages - Store metadata — use
this.metadatato expose extracted data (URLs, hashtags, mentions) to consumers