-
Notifications
You must be signed in to change notification settings - Fork 103
Expand file tree
/
Copy pathsearch.html
More file actions
143 lines (123 loc) · 5.04 KB
/
search.html
File metadata and controls
143 lines (123 loc) · 5.04 KB
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
---
product-type: none
search: exclude
layout: default
title: Full Article Search
permalink: /search.html
---
<div class="full-text-search">
<h1>Search</h1>
<small>Search by text and code inside documentation pages.</small>
<div id="searchbox"></div>
<div id="hits"></div>
<div id="pagination"></div>
</div>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.css@7/themes/satellite-min.css"/>
<script src="https://cdn.jsdelivr.net/npm/algoliasearch@4"></script>
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4"></script>
<script>
let debounceTimer;
const search = instantsearch({
indexName: 'spryker_full_content',
searchClient: algoliasearch('SF7W0R2XNG', '8f2c94685deea955c12e82e73f333f4a'),
routing: {
stateMapping: {
stateToRoute(uiState) {
const indexUiState = uiState['spryker_full_content'] || {};
return {
q: indexUiState.query,
page: indexUiState.page,
};
},
routeToState(routeState) {
return {
spryker_full_content: {
query: routeState.q,
page: routeState.page,
},
};
},
},
},
searchFunction(helper) {
const query = helper.state.query.trim();
if (query.length < 3) {
document.querySelector('#hits').innerHTML = '';
document.querySelector('#pagination').innerHTML = '';
return;
}
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
helper.search();
}, 500);
},
});
search.addWidgets([
instantsearch.widgets.searchBox({
container: '#searchbox',
placeholder: 'Enter search query...',
searchAsYouType: true,
autofocus: true,
}),
instantsearch.widgets.hits({
container: '#hits',
templates: {
item(hit) {
const url = hit.url_without_anchor;
const title = hit.title ? hit.title : hit.url_without_anchor;
const description = hit.description ? hit.description : '';
const highlight = hit._highlightResult || {};
const headers = Array.isArray(highlight.headers)
? highlight.headers
.filter(header => header?.matchLevel !== 'none')
.slice(0, 3)
.filter(header => header?.value)
.map(header => `<p class="header">${header.value}</p>`)
.join('')
: '';
const keywords = Array.isArray(highlight.keywords)
? highlight.keywords
.filter(keyword => keyword?.matchLevel !== 'none')
.filter(keyword => keyword?.value)
.map(keyword => `<p class="header">${keyword.value}</p>`)
.join('')
: '';
const contentSnippets = extractMarkedContext(
highlight.content?.matchLevel !== 'none' ? highlight.content.value : ''
);
const contentSnippetsHtml = contentSnippets.length ? `<div class="highlight-content">...${contentSnippets}</div>` : '';
return `
<div class="hit">
<a href="${url}">${title}</a>
${headers || `<p class="header">${title}</p>`}
${description.length > 0 ? `<p>${description}</p>` : ''}
${keywords}
${contentSnippetsHtml}
</div>
`;
}
}
}),
instantsearch.widgets.pagination({
container: '#pagination'
})
]);
search.start();
function extractMarkedContext(text, maxMarks = 5, contextSize = 5) {
const regex = /<mark>(.*?)<\/mark>/gi;
let matches = [...text.matchAll(regex)];
let results = [];
for (let i = 0; i < Math.min(maxMarks, matches.length); i++) {
const match = matches[i];
const before = text.slice(0, match.index).trim();
const after = text.slice(match.index + match[0].length).trim();
// Split into words
const beforeWords = before.split(/\s+/).slice(-contextSize);
const afterWords = after.split(/\s+/).slice(0, contextSize);
// Build snippet
const snippet = `${beforeWords.join(" ")} ${match[0]} ${afterWords.join(" ")}`;
results.push(snippet);
}
return results.join(" ... ");
}
</script>