mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
chore: slightly enhance Highlight
This commit is contained in:
parent
36d6421f6e
commit
7600ba43fd
1 changed files with 26 additions and 22 deletions
|
|
@ -1,41 +1,45 @@
|
|||
import * as React from 'react'
|
||||
|
||||
export const Highlight = React.memo(function Highlight(props: { text: string; match?: RegExp }) {
|
||||
const { text, match } = props
|
||||
const $match = React.useMemo(() => {
|
||||
if (match instanceof RegExp) {
|
||||
if (match.flags.includes('g')) return match
|
||||
return new RegExp(match.source, 'g' + match.flags)
|
||||
}
|
||||
return null
|
||||
}, [match])
|
||||
export const Highlight = function Highlight({ text, match }: { text: string; match?: RegExp }) {
|
||||
const $match = React.useMemo(
|
||||
() =>
|
||||
match instanceof RegExp
|
||||
? match.flags.includes('g')
|
||||
? match
|
||||
: new RegExp(match.source, 'g' + match.flags)
|
||||
: null,
|
||||
[match],
|
||||
)
|
||||
|
||||
const chunks = useChunks(text, $match)
|
||||
const chunks = React.useMemo(() => getChunks(text, $match), [text, $match])
|
||||
|
||||
return <>{chunks.map(([type, text], key) => React.createElement(type, { key }, text))}</>
|
||||
})
|
||||
}
|
||||
|
||||
function useChunks(text: string, $match: RegExp | null) {
|
||||
const contents: [string, string][] = []
|
||||
if ($match === null) return [['span', text]]
|
||||
type ElementMeta = [tag: string, content: string]
|
||||
function getChunks(text: string, match: RegExp | null): ElementMeta[] {
|
||||
const contents: ElementMeta[] = []
|
||||
|
||||
const matchedPieces = Array.from(text.matchAll($match)).map(
|
||||
if (match === null) {
|
||||
contents.push(['span', text])
|
||||
return contents
|
||||
}
|
||||
|
||||
const matchedPieces = Array.from(text.matchAll(match)).map(
|
||||
([text, highlightText = text]) => highlightText,
|
||||
)
|
||||
const preservedPieces = text.split($match)
|
||||
const preservedPieces = text.split(match)
|
||||
|
||||
const push = (type: string, text: string) => {
|
||||
if (!text) return
|
||||
const last = contents[contents.length - 1]
|
||||
if (last && last[0] === type) last[1] += text
|
||||
else contents.push([type, text])
|
||||
}
|
||||
|
||||
let i = 0
|
||||
while (i < Math.max(matchedPieces.length, preservedPieces.length)) {
|
||||
push('span', preservedPieces[i])
|
||||
push('mark', matchedPieces[i])
|
||||
++i
|
||||
const max = Math.max(matchedPieces.length, preservedPieces.length)
|
||||
for (let i = 0; i < max; ++i) {
|
||||
preservedPieces[i] && push('span', preservedPieces[i])
|
||||
matchedPieces[i] && push('mark', matchedPieces[i])
|
||||
}
|
||||
return contents
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue