diff --git a/MenuConfig.xml b/MenuConfig.xml index 3920f536a5..4811099275 100644 --- a/MenuConfig.xml +++ b/MenuConfig.xml @@ -109,7 +109,7 @@ - + diff --git a/concepts/05 UI Components/Chat/13 Markdown Support.md b/concepts/05 UI Components/Chat/13 Markdown Support.md new file mode 100644 index 0000000000..3a8d028de1 --- /dev/null +++ b/concepts/05 UI Components/Chat/13 Markdown Support.md @@ -0,0 +1,138 @@ +You often need to convert Chat messages from Markdown to HTML since Chat supports HTML. This is useful when using OpenAI or supporting Markdown in user inputs. + +To support Markdown, use a third-party library for conversion. The [unified](https://unifiedjs.com/explore/package/unified/) + [remark](https://unifiedjs.com/explore/package/remark/) + [rehype](https://unifiedjs.com/explore/package/rehype/) stack is a good option, as shown in our AI integration demo: + +#include btn-open-demo with { + href: "https://js.devexpress.com/Demos/WidgetsGallery/Demo/Chat/AIAndChatbotIntegration/" +} + +This powerful stack supports various extensions and allows control over different conversion stages. For a simpler, lightweight solution, you can use libraries such as [micromark](https://github.com/micromark/micromark). + +Regardless of the library choice, convert the message text within the [messageTemplate](/Documentation/ApiReference/UI_Components/dxChat/Configuration/#messageTemplate) property: + +--- +##### jQuery + + + + +
+ + + $(() => { + const chat = $("#chat") + .dxChat({ + onMessageEntered: ({ component, message }) => { + component.renderMessage(message); + }, + messageTemplate: (e, element) => { + const htmlText = $(micromark(e.message.text)).html(); + $("
").html(htmlText).appendTo(element); + } + }) + .dxChat("instance"); + }); + +##### Angular + + + +
+
+
+
+ + + import { DxChatTypes } from "devextreme-angular/ui/chat"; + import { micromark } from 'micromark'; + // ... + export class AppComponent { + messages: DxChatTypes.Message[] = []; + + onMessageEntered(e: DxChatTypes.MessageEnteredEvent) { + if (e.message) { + this.messages = [...this.messages, e.message]; + } + } + convertToHtml(text: string) { + let html = micromark(text); + return html.replace(/^

/, '').replace(/<\/p>$/, ''); + } + } + +##### Vue + + + + + + +##### React + + + import { Chat } from 'devextreme-react'; + import { ChatTypes } from 'devextreme-react/cjs/chat'; + import 'devextreme/dist/css/dx.light.css' + import { useCallback, useState } from 'react'; + import HTMLReactParser from 'html-react-parser'; + import { micromark } from 'micromark'; + + const convertToHtml = (text: string) => { + let html = micromark(text); + return html.replace(/^

/, '').replace(/<\/p>$/, ''); + } + const messageRender = (data: ChatTypes.MessageTemplateData) => { + return (HTMLReactParser(convertToHtml(data.message!.text!))); + } + + export default function App() { + const [messages, setMessages] = useState([]); + const onMessageEntered = useCallback((e: ChatTypes.MessageEnteredEvent) => { + setMessages((prevMessages) => [...prevMessages, e.message!]); + }, []); + return( + + ); + } + +--- \ No newline at end of file