Monorepo for Tangled
tangled.org
1package pages
2
3import "sort"
4
5// helper functions to render search match highlights
6
7// mergeIntervals sorts half-open rune intervals and merges overlapping/adjacent ones.
8func mergeIntervals(in [][2]int) [][2]int {
9 if len(in) < 2 {
10 return in
11 }
12 sort.Slice(in, func(i, j int) bool { return in[i][0] < in[j][0] })
13 out := in[:1]
14 for _, iv := range in[1:] {
15 last := &out[len(out)-1]
16 if iv[0] <= last[1] {
17 if iv[1] > last[1] {
18 last[1] = iv[1]
19 }
20 continue
21 }
22 out = append(out, iv)
23 }
24 return out
25}
26
27// spanRunes splits runes into alternating unmatched/matched ChunkSpans using the
28// (sorted, merged) match intervals. Returns nil for an empty line.
29func spanRunes(runes []rune, intervals [][2]int) []ChunkSpan {
30 if len(runes) == 0 {
31 return nil
32 }
33 if len(intervals) == 0 {
34 return []ChunkSpan{{Text: string(runes)}}
35 }
36 var spans []ChunkSpan
37 pos := 0
38 for _, iv := range intervals {
39 if iv[0] > pos {
40 spans = append(spans, ChunkSpan{Text: string(runes[pos:iv[0]])})
41 }
42 spans = append(spans, ChunkSpan{Text: string(runes[iv[0]:iv[1]]), Match: true})
43 pos = iv[1]
44 }
45 if pos < len(runes) {
46 spans = append(spans, ChunkSpan{Text: string(runes[pos:])})
47 }
48 return spans
49}