GitHub

Original file line numberDiff line numberDiff line change

@@ -1,6 +1,30 @@

11

import type { FuseResult, FuseResultMatch } from 'fuse.js'

22

import type { GetItemKeys } from '../types/utils'

33
4+

const htmlEscapes: Record<string, string> = {

5+

'&': '&amp;',

6+

'<': '&lt;',

7+

'>': '&gt;',

8+

'"': '&quot;',

9+

'\'': '&#39;'

10+

}

11+
12+

function escapeHTML(str: string): string {

13+

return str.replace(/[&<>"']/g, char => htmlEscapes[char]!)

14+

}

15+
16+

// Check if string is already HTML-escaped to avoid double-escaping

17+

function isAlreadyEscaped(str: string): boolean {

18+

return /&(?:amp|lt|gt|quot|#39);/.test(str)

19+

}

20+
21+

function sanitize(str: string): string {

22+

if (isAlreadyEscaped(str)) {

23+

return str

24+

}

25+

return escapeHTML(str)

26+

}

27+
428

function truncateHTMLFromStart(html: string, maxLength: number) {

529

let truncated = ''

630

let totalLength = 0

@@ -49,16 +73,16 @@ export function highlight<T>(item: T & { matches?: FuseResult<T>['matches'] }, s

4973

const isMatched = (lastIndiceNextIndex - region[0]) >= searchTerm.length

5074
5175

content += [

52-

value.substring(nextUnhighlightedRegionStartingIndex, region[0]),

76+

sanitize(value.substring(nextUnhighlightedRegionStartingIndex, region[0])),

5377

isMatched && `<mark>`,

54-

value.substring(region[0], lastIndiceNextIndex),

78+

sanitize(value.substring(region[0], lastIndiceNextIndex)),

5579

isMatched && '</mark>'

5680

].filter(Boolean).join('')

5781
5882

nextUnhighlightedRegionStartingIndex = lastIndiceNextIndex

5983

})

6084
61-

content += value.substring(nextUnhighlightedRegionStartingIndex)

85+

content += sanitize(value.substring(nextUnhighlightedRegionStartingIndex))

6286
6387

const markIndex = content.indexOf('<mark>')

6488

if (markIndex !== -1) {

Read the original on github.com ↗