Skip to content

Commit c95129a

Browse files
committed
Optimize
1 parent fba3cc3 commit c95129a

File tree

1 file changed

+26
-23
lines changed
  • src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi

1 file changed

+26
-23
lines changed

src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/ChatMessage.tsx

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,26 @@ import {
2020
import { css } from '@emotion/react'
2121
import DOMPurify from 'dompurify'
2222
import hljs from 'highlight.js/lib/core'
23-
import { marked } from 'marked'
23+
import {Marked, RendererObject, Tokens} from 'marked'
2424
import * as React from 'react'
25-
import { useEffect } from 'react'
26-
import { $, $$ } from 'select-dom'
25+
import { useEffect, useMemo } from 'react'
26+
27+
// Create the marked instance once globally (renderer never changes)
28+
const createMarkedInstance = () => {
29+
const renderer: RendererObject = {
30+
code({ text, lang }: Tokens.Code): string {
31+
const highlighted = lang ? hljs.highlight(text, { language: lang }).value : hljs.highlightAuto(text).value;
32+
return `<div class="highlight">
33+
<pre>
34+
<code class="language-${lang}">${highlighted}</code>
35+
</pre>
36+
</div>`;
37+
}
38+
}
39+
return new Marked({ renderer })
40+
}
41+
42+
const markedInstance = createMarkedInstance() // Created once globally
2743

2844
interface ChatMessageProps {
2945
message: ChatMessageType
@@ -157,25 +173,12 @@ export const ChatMessage = ({
157173
: message.content
158174

159175
const hasError = message.status === 'error' || !!error
160-
161-
const html = marked.parse(content)
162-
const sanitized = DOMPurify.sanitize(html as string)
163-
const tempDiv = document.createElement('div')
164-
tempDiv.innerHTML = sanitized
165-
166-
// Add highlight wrappers and highlight code blocks
167-
$$('pre', tempDiv).forEach((preEl) => {
168-
const wrapper = document.createElement('div')
169-
wrapper.className = 'highlight'
170-
preEl.parentNode?.insertBefore(wrapper, preEl)
171-
wrapper.appendChild(preEl)
172-
const codeEl = $('code', preEl)
173-
if (codeEl) {
174-
hljs.highlightElement(codeEl)
175-
}
176-
})
177-
178-
const parsed = tempDiv.innerHTML
176+
177+
// Memoize the parsed HTML to avoid re-parsing on every render
178+
const parsed = useMemo(() => {
179+
const html = markedInstance.parse(content) as string
180+
return DOMPurify.sanitize(html)
181+
}, [content])
179182
const ref = React.useRef<HTMLDivElement>(null)
180183

181184
// Initialize copy buttons after DOM is updated
@@ -195,7 +198,7 @@ export const ChatMessage = ({
195198
}, 100)
196199
return () => clearTimeout(timer)
197200
}
198-
}, [parsed, isComplete])
201+
}, [isComplete]) // Only depend on isComplete, not parsed
199202

200203
return (
201204
<EuiFlexGroup

0 commit comments

Comments
 (0)