-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
SearchResult.tsx
94 lines (87 loc) · 2.93 KB
/
SearchResult.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { decode } from 'he'
import FileIcon from 'mdi-react/FileIcon'
import React from 'react'
import { ResultContainer } from '../../../shared/src/components/ResultContainer'
import * as GQL from '../../../shared/src/graphql/schema'
import { renderMarkdown } from '../../../shared/src/util/markdown'
import { SearchResultMatch } from './SearchResultMatch'
export interface HighlightRange {
/**
* The 0-based line number that this highlight appears in
*/
line: number
/**
* The 0-based character offset to start highlighting at
*/
character: number
/**
* The number of characters to highlight
*/
length: number
}
interface Props {
result: GQL.GenericSearchResultInterface
isLightTheme: boolean
}
export class SearchResult extends React.Component<Props> {
constructor(props: Props) {
super(props)
}
private renderTitle = () => (
<div className="search-result__title">
<span
dangerouslySetInnerHTML={{
__html: this.props.result.label.html
? decode(this.props.result.label.html)
: renderMarkdown(this.props.result.label.text),
}}
/>
{this.props.result.detail && (
<>
<span className="search-result__spacer" />
<small
dangerouslySetInnerHTML={{
__html: this.props.result.detail.html
? decode(this.props.result.detail.html)
: renderMarkdown(this.props.result.detail.text),
}}
/>
</>
)}
</div>
)
private renderBody = () => (
<>
{this.props.result.matches.map((match, index) => {
const highlightRanges: HighlightRange[] = []
match.highlights.map(highlight =>
highlightRanges.push({
line: highlight.line,
character: highlight.character,
length: highlight.length,
})
)
return (
<SearchResultMatch
key={`item.url#${index}`}
item={match}
highlightRanges={highlightRanges}
isLightTheme={this.props.isLightTheme}
/>
)
})}
</>
)
public render(): JSX.Element {
return (
<ResultContainer
stringIcon={this.props.result.icon}
icon={FileIcon}
collapsible={this.props.result && this.props.result.matches.length > 0}
defaultExpanded={true}
title={this.renderTitle()}
expandedChildren={this.renderBody()}
/>
)
}
}