mirror of
https://github.com/EKKOLearnAI/hermes-web-ui.git
synced 2026-05-25 13:30:14 +00:00
7da934fe8b
Revert the dynamic import() for i18n locales and highlight.js core+ registration from #696. Dynamic imports create separate chunk files that cause 404 errors for users after updating when the browser still references old chunk hashes. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
82 lines
2.8 KiB
TypeScript
82 lines
2.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
const highlightJsMock = vi.hoisted(() => ({
|
|
getLanguage: vi.fn((lang?: string) => ['shell', 'xml', 'yaml', 'bash', 'json'].includes(lang || '')),
|
|
highlight: vi.fn((content: string, { language }: { language: string }) => ({
|
|
value: `<span class="mock-${language}">${content}</span>`,
|
|
})),
|
|
registerLanguage: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('highlight.js', () => ({
|
|
default: highlightJsMock,
|
|
}))
|
|
|
|
import { normalizeHighlightLanguage, renderHighlightedCodeBlock } from '@/components/hermes/chat/highlight'
|
|
|
|
describe('highlight helper', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
highlightJsMock.getLanguage.mockImplementation((lang?: string) => ['shell', 'xml', 'yaml', 'bash', 'json'].includes(lang || ''))
|
|
highlightJsMock.highlight.mockImplementation((content: string, { language }: { language: string }) => ({
|
|
value: `<span class="mock-${language}">${content}</span>`,
|
|
}))
|
|
})
|
|
|
|
it.each([
|
|
['vue', 'xml'],
|
|
['yml', 'yaml'],
|
|
['sh', 'bash'],
|
|
['zsh', 'bash'],
|
|
['shellscript', 'bash'],
|
|
['shell', 'shell'],
|
|
])('normalizes %s to %s', (input, expected) => {
|
|
expect(normalizeHighlightLanguage(input)).toBe(expected)
|
|
})
|
|
|
|
it('uses a delegated copy attribute instead of inline javascript', () => {
|
|
const html = renderHighlightedCodeBlock('x', 'json', 'Copy')
|
|
|
|
expect(html).toContain('data-copy-code="true"')
|
|
expect(html).not.toContain('onclick=')
|
|
})
|
|
|
|
it('preserves shell-session highlighting instead of remapping shell fences to bash', () => {
|
|
const html = renderHighlightedCodeBlock('$ ls\nfoo.txt\n', 'shell', 'Copy')
|
|
|
|
expect(highlightJsMock.highlight).toHaveBeenCalledWith('$ ls\nfoo.txt\n', {
|
|
language: 'shell',
|
|
ignoreIllegals: true,
|
|
})
|
|
expect(html).toContain('class="code-lang">shell</span>')
|
|
})
|
|
|
|
it('skips highlighting for large known-language blocks when a render limit is set', () => {
|
|
const html = renderHighlightedCodeBlock('x'.repeat(5000), 'vue', 'Copy', {
|
|
maxHighlightLength: 2000,
|
|
})
|
|
|
|
expect(highlightJsMock.highlight).not.toHaveBeenCalled()
|
|
expect(html).toContain('class="code-lang">vue</span>')
|
|
})
|
|
|
|
it('falls back to escaped plaintext for unsupported fence labels', () => {
|
|
const html = renderHighlightedCodeBlock('<tag>', 'unknown', 'Copy')
|
|
|
|
expect(highlightJsMock.highlight).not.toHaveBeenCalled()
|
|
expect(html).toContain('<tag>')
|
|
expect(html).toContain('class="code-lang">unknown</span>')
|
|
})
|
|
|
|
it('falls back to escaped plaintext when direct highlighting throws', () => {
|
|
highlightJsMock.highlight.mockImplementationOnce(() => {
|
|
throw new Error('boom')
|
|
})
|
|
|
|
const html = renderHighlightedCodeBlock('<tag>', 'vue', 'Copy')
|
|
|
|
expect(html).toContain('<tag>')
|
|
expect(html).toContain('class="code-lang">vue</span>')
|
|
})
|
|
})
|