feat(renderer): KaTeX math rendering for $inline$ and $$block$$ (M10.6)

- Lazy-loads KaTeX (~70KB) on first math detected
- Inline $...$ and block $$...$$ LaTeX support
- Falls back to <code> for invalid LaTeX
- Batch render after markdown, not during streaming

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-03 23:56:12 +00:00
co-authored by Claude Opus 4.6
parent c070e76515
commit e7961c608b
4 changed files with 98 additions and 4 deletions
@@ -323,8 +323,9 @@
</template>
<script setup lang="ts">
import { computed, ref, nextTick } from 'vue'
import { computed, ref, nextTick, watch } from 'vue'
import MarkdownIt from 'markdown-it'
import { hasMath, renderMathInHtml } from '@/composables/useMathRenderer'
import ContextMenu from '@/components/ui/ContextMenu.vue'
import ContextMenuItem from '@/components/ui/ContextMenuItem.vue'
import type { Message, WebSearchResult } from '@aiui/core/types/message'
@@ -493,9 +494,18 @@ const displayText = computed(() => {
return text
})
const renderedMarkdown = computed(() => {
return md.render(displayText.value)
})
const baseMarkdown = computed(() => md.render(displayText.value))
const renderedMarkdown = ref('')
// Render math after markdown, batch on content change
watch(baseMarkdown, async (html) => {
if (hasMath(displayText.value)) {
renderedMarkdown.value = html // Show immediately
renderedMarkdown.value = await renderMathInHtml(html)
} else {
renderedMarkdown.value = html
}
}, { immediate: true })
const formattedTime = computed(() => {
const d = new Date(props.message.timestamp)