[READ-ONLY] a fast, modern browser for the npm registry
at main 114 lines 4.0 kB view raw
1import { describe, expect, it } from 'vitest' 2import { escapeRawGt, highlightCodeBlock } from '../../../../server/utils/shiki' 3 4describe('escapeRawGt', () => { 5 it('should encode > in arrow functions', () => { 6 const input = '<span style="color:#F97583">=></span>' 7 const output = escapeRawGt(input) 8 expect(output).toBe('<span style="color:#F97583">=&gt;</span>') 9 }) 10 11 it('should encode > in comparison operators', () => { 12 const input = '<span>x > 5</span>' 13 const output = escapeRawGt(input) 14 expect(output).toBe('<span>x &gt; 5</span>') 15 }) 16 17 it('should encode multiple > in text content', () => { 18 const input = '<span>a > b > c</span>' 19 const output = escapeRawGt(input) 20 expect(output).toBe('<span>a &gt; b &gt; c</span>') 21 }) 22 23 it('should not affect HTML tag structure', () => { 24 const input = '<span class="test"><code>text</code></span>' 25 const output = escapeRawGt(input) 26 expect(output).toBe('<span class="test"><code>text</code></span>') 27 }) 28 29 it('should not affect attributes containing >', () => { 30 // Attributes with > are already encoded by Shiki, but test anyway 31 const input = '<span title="a &gt; b">text</span>' 32 const output = escapeRawGt(input) 33 expect(output).toBe('<span title="a &gt; b">text</span>') 34 }) 35 36 it('should handle empty text content', () => { 37 const input = '<span></span><code></code>' 38 const output = escapeRawGt(input) 39 expect(output).toBe('<span></span><code></code>') 40 }) 41 42 it('should handle text without special characters', () => { 43 const input = '<span>hello world</span>' 44 const output = escapeRawGt(input) 45 expect(output).toBe('<span>hello world</span>') 46 }) 47 48 it('should handle nested spans (Shiki output structure)', () => { 49 const input = 50 '<span class="line"><span style="color:#F97583">const</span><span> x = () =></span><span> 5</span></span>' 51 const output = escapeRawGt(input) 52 expect(output).toBe( 53 '<span class="line"><span style="color:#F97583">const</span><span> x = () =&gt;</span><span> 5</span></span>', 54 ) 55 }) 56 57 it('should handle >= operator', () => { 58 const input = '<span>x >= 5</span>' 59 const output = escapeRawGt(input) 60 expect(output).toBe('<span>x &gt;= 5</span>') 61 }) 62 63 it('should handle generic type syntax', () => { 64 const input = '<span>Array&lt;T></span>' 65 const output = escapeRawGt(input) 66 // The < is already encoded, the > should be encoded 67 expect(output).toBe('<span>Array&lt;T&gt;</span>') 68 }) 69}) 70 71describe('highlightCodeBlock', () => { 72 it('should highlight TypeScript code', async () => { 73 const code = 'const x = 1' 74 const html = await highlightCodeBlock(code, 'typescript') 75 76 expect(html).toContain('<pre') 77 expect(html).toContain('const') 78 expect(html).toContain('shiki') 79 }) 80 81 it('should encode > in arrow functions', async () => { 82 const code = 'const fn = () => 5' 83 const html = await highlightCodeBlock(code, 'typescript') 84 85 // The > in => should be encoded 86 expect(html).toContain('=&gt;') 87 expect(html).not.toMatch(/=>(?!&)/) // no raw => (except in &gt;) 88 }) 89 90 it('should encode > in generic types', async () => { 91 const code = 'const x: Array<string> = []' 92 const html = await highlightCodeBlock(code, 'typescript') 93 94 // Should have encoded > 95 expect(html).toContain('&gt;') 96 }) 97 98 it('should fall back to plain code for unknown languages', async () => { 99 const code = 'some random code > with special < chars' 100 const html = await highlightCodeBlock(code, 'unknownlang123') 101 102 expect(html).toContain('&gt;') 103 expect(html).toContain('&lt;') 104 expect(html).toContain('language-unknownlang123') 105 }) 106 107 it('should escape special characters in fallback', async () => { 108 const code = '<script>alert("xss")</script>' 109 const html = await highlightCodeBlock(code, 'unknownlang123') 110 111 expect(html).toContain('&lt;script&gt;') 112 expect(html).not.toContain('<script>') 113 }) 114})