@docusaurus/theme-search-algolia 2.0.0-beta.15 → 2.0.0-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client/index.js +1 -1
- package/lib/client/useAlgoliaContextualFacetFilters.js +6 -6
- package/lib/index.js +96 -67
- package/lib/templates/opensearch.d.ts +1 -1
- package/lib/templates/opensearch.js +7 -7
- package/lib/theme/SearchBar/index.d.ts +1 -2
- package/lib/theme/SearchBar/index.js +181 -125
- package/lib/theme/SearchPage/index.d.ts +1 -2
- package/lib/theme/SearchPage/index.js +381 -224
- package/lib/validateThemeConfig.d.ts +1 -1
- package/lib/validateThemeConfig.js +37 -27
- package/package.json +18 -17
- package/src/deps.d.ts +10 -0
- package/src/index.ts +41 -26
- package/src/templates/opensearch.ts +5 -5
- package/src/theme/SearchBar/index.tsx +16 -14
- package/src/theme/SearchPage/index.tsx +6 -10
- package/src/theme-search-algolia.d.ts +3 -4
- package/src/types.d.ts +0 -4
- package/src/validateThemeConfig.ts +9 -5
- package/lib/theme/SearchMetadata/index.d.ts +0 -11
- package/lib/theme/SearchMetadata/index.js +0 -20
- package/src/theme/SearchMetadata/index.tsx +0 -28
|
@@ -5,294 +5,451 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
/* eslint-disable jsx-a11y/no-autofocus */
|
|
8
|
-
|
|
9
|
-
import React, { useEffect, useState, useReducer, useRef } from 'react';
|
|
8
|
+
import React, {useEffect, useState, useReducer, useRef} from 'react';
|
|
10
9
|
import algoliaSearch from 'algoliasearch/lite';
|
|
11
10
|
import algoliaSearchHelper from 'algoliasearch-helper';
|
|
12
11
|
import clsx from 'clsx';
|
|
13
12
|
import Head from '@docusaurus/Head';
|
|
14
13
|
import Link from '@docusaurus/Link';
|
|
15
14
|
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
16
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
useTitleFormatter,
|
|
17
|
+
usePluralForm,
|
|
18
|
+
isRegexpStringMatch,
|
|
19
|
+
useDynamicCallback,
|
|
20
|
+
useSearchPage,
|
|
21
|
+
} from '@docusaurus/theme-common';
|
|
17
22
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
18
|
-
import {
|
|
23
|
+
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
19
24
|
import Layout from '@theme/Layout';
|
|
20
|
-
import Translate, {
|
|
25
|
+
import Translate, {translate} from '@docusaurus/Translate';
|
|
21
26
|
import styles from './styles.module.css';
|
|
22
27
|
// Very simple pluralization: probably good enough for now
|
|
23
28
|
function useDocumentsFoundPlural() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
const {selectMessage} = usePluralForm();
|
|
30
|
+
return (count) =>
|
|
31
|
+
selectMessage(
|
|
32
|
+
count,
|
|
33
|
+
translate(
|
|
34
|
+
{
|
|
35
|
+
id: 'theme.SearchPage.documentsFound.plurals',
|
|
36
|
+
description:
|
|
37
|
+
'Pluralized label for "{count} documents found". Use as much plural forms (separated by "|") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)',
|
|
38
|
+
message: 'One document found|{count} documents found',
|
|
39
|
+
},
|
|
40
|
+
{count},
|
|
41
|
+
),
|
|
42
|
+
);
|
|
30
43
|
}
|
|
31
44
|
function useDocsSearchVersionsHelpers() {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
const allDocsData = useAllDocsData();
|
|
46
|
+
// State of the version select menus / algolia facet filters
|
|
47
|
+
// docsPluginId -> versionName map
|
|
48
|
+
const [searchVersions, setSearchVersions] = useState(() =>
|
|
49
|
+
Object.entries(allDocsData).reduce(
|
|
50
|
+
(acc, [pluginId, pluginData]) => ({
|
|
36
51
|
...acc,
|
|
37
52
|
[pluginId]: pluginData.versions[0].name,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
}),
|
|
54
|
+
{},
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
// Set the value of a single select menu
|
|
58
|
+
const setSearchVersion = (pluginId, searchVersion) =>
|
|
59
|
+
setSearchVersions((s) => ({...s, [pluginId]: searchVersion}));
|
|
60
|
+
const versioningEnabled = Object.values(allDocsData).some(
|
|
61
|
+
(docsData) => docsData.versions.length > 1,
|
|
62
|
+
);
|
|
63
|
+
return {
|
|
64
|
+
allDocsData,
|
|
65
|
+
versioningEnabled,
|
|
66
|
+
searchVersions,
|
|
67
|
+
setSearchVersion,
|
|
68
|
+
};
|
|
48
69
|
}
|
|
49
70
|
// We want to display one select per versioned docs plugin instance
|
|
50
|
-
function SearchVersionSelectList({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
function SearchVersionSelectList({docsSearchVersionsHelpers}) {
|
|
72
|
+
const versionedPluginEntries = Object.entries(
|
|
73
|
+
docsSearchVersionsHelpers.allDocsData,
|
|
74
|
+
)
|
|
75
|
+
// Do not show a version select for unversioned docs plugin instances
|
|
76
|
+
.filter(([, docsData]) => docsData.versions.length > 1);
|
|
77
|
+
return (
|
|
78
|
+
<div
|
|
79
|
+
className={clsx(
|
|
80
|
+
'col',
|
|
81
|
+
'col--3',
|
|
82
|
+
'padding-left--none',
|
|
83
|
+
styles.searchVersionColumn,
|
|
84
|
+
)}>
|
|
55
85
|
{versionedPluginEntries.map(([pluginId, docsData]) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
algolia: { appId, apiKey, indexName, externalUrlRegex }, }, }, i18n: { currentLocale }, } = useDocusaurusContext();
|
|
67
|
-
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
68
|
-
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
69
|
-
const { searchQuery, setSearchQuery } = useSearchPage();
|
|
70
|
-
const initialSearchResultState = {
|
|
71
|
-
items: [],
|
|
72
|
-
query: null,
|
|
73
|
-
totalResults: null,
|
|
74
|
-
totalPages: null,
|
|
75
|
-
lastPage: null,
|
|
76
|
-
hasMore: null,
|
|
77
|
-
loading: null,
|
|
78
|
-
};
|
|
79
|
-
const [searchResultState, searchResultStateDispatcher] = useReducer((prevState, data) => {
|
|
80
|
-
switch (data.type) {
|
|
81
|
-
case 'reset': {
|
|
82
|
-
return initialSearchResultState;
|
|
83
|
-
}
|
|
84
|
-
case 'loading': {
|
|
85
|
-
return { ...prevState, loading: true };
|
|
86
|
-
}
|
|
87
|
-
case 'update': {
|
|
88
|
-
if (searchQuery !== data.value.query) {
|
|
89
|
-
return prevState;
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
...data.value,
|
|
93
|
-
items: data.value.lastPage === 0
|
|
94
|
-
? data.value.items
|
|
95
|
-
: prevState.items.concat(data.value.items),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
case 'advance': {
|
|
99
|
-
const hasMore = prevState.totalPages > prevState.lastPage + 1;
|
|
100
|
-
return {
|
|
101
|
-
...prevState,
|
|
102
|
-
lastPage: hasMore ? prevState.lastPage + 1 : prevState.lastPage,
|
|
103
|
-
hasMore,
|
|
104
|
-
};
|
|
86
|
+
const labelPrefix =
|
|
87
|
+
versionedPluginEntries.length > 1 ? `${pluginId}: ` : '';
|
|
88
|
+
return (
|
|
89
|
+
<select
|
|
90
|
+
key={pluginId}
|
|
91
|
+
onChange={(e) =>
|
|
92
|
+
docsSearchVersionsHelpers.setSearchVersion(
|
|
93
|
+
pluginId,
|
|
94
|
+
e.target.value,
|
|
95
|
+
)
|
|
105
96
|
}
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
defaultValue={docsSearchVersionsHelpers.searchVersions[pluginId]}
|
|
98
|
+
className={styles.searchVersionInput}>
|
|
99
|
+
{docsData.versions.map((version, i) => (
|
|
100
|
+
<option
|
|
101
|
+
key={i}
|
|
102
|
+
label={`${labelPrefix}${version.label}`}
|
|
103
|
+
value={version.name}
|
|
104
|
+
/>
|
|
105
|
+
))}
|
|
106
|
+
</select>
|
|
107
|
+
);
|
|
108
|
+
})}
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
export default function SearchPage() {
|
|
113
|
+
const {
|
|
114
|
+
siteConfig: {themeConfig},
|
|
115
|
+
i18n: {currentLocale},
|
|
116
|
+
} = useDocusaurusContext();
|
|
117
|
+
const {
|
|
118
|
+
algolia: {appId, apiKey, indexName, externalUrlRegex},
|
|
119
|
+
} = themeConfig;
|
|
120
|
+
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
121
|
+
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
122
|
+
const {searchQuery, setSearchQuery} = useSearchPage();
|
|
123
|
+
const initialSearchResultState = {
|
|
124
|
+
items: [],
|
|
125
|
+
query: null,
|
|
126
|
+
totalResults: null,
|
|
127
|
+
totalPages: null,
|
|
128
|
+
lastPage: null,
|
|
129
|
+
hasMore: null,
|
|
130
|
+
loading: null,
|
|
131
|
+
};
|
|
132
|
+
const [searchResultState, searchResultStateDispatcher] = useReducer(
|
|
133
|
+
(prevState, data) => {
|
|
134
|
+
switch (data.type) {
|
|
135
|
+
case 'reset': {
|
|
136
|
+
return initialSearchResultState;
|
|
108
137
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const algoliaHelper = algoliaSearchHelper(algoliaClient, indexName, {
|
|
112
|
-
hitsPerPage: 15,
|
|
113
|
-
advancedSyntax: true,
|
|
114
|
-
disjunctiveFacets: ['language', 'docusaurus_tag'],
|
|
115
|
-
});
|
|
116
|
-
algoliaHelper.on('result', ({ results: { query, hits, page, nbHits, nbPages } }) => {
|
|
117
|
-
if (query === '' || !(hits instanceof Array)) {
|
|
118
|
-
searchResultStateDispatcher({ type: 'reset' });
|
|
119
|
-
return;
|
|
138
|
+
case 'loading': {
|
|
139
|
+
return {...prevState, loading: true};
|
|
120
140
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
141
|
+
case 'update': {
|
|
142
|
+
if (searchQuery !== data.value.query) {
|
|
143
|
+
return prevState;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
...data.value,
|
|
147
|
+
items:
|
|
148
|
+
data.value.lastPage === 0
|
|
149
|
+
? data.value.items
|
|
150
|
+
: prevState.items.concat(data.value.items),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
case 'advance': {
|
|
154
|
+
const hasMore = prevState.totalPages > prevState.lastPage + 1;
|
|
155
|
+
return {
|
|
156
|
+
...prevState,
|
|
157
|
+
lastPage: hasMore ? prevState.lastPage + 1 : prevState.lastPage,
|
|
158
|
+
hasMore,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
default:
|
|
162
|
+
return prevState;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
initialSearchResultState,
|
|
166
|
+
);
|
|
167
|
+
const algoliaClient = algoliaSearch(appId, apiKey);
|
|
168
|
+
const algoliaHelper = algoliaSearchHelper(algoliaClient, indexName, {
|
|
169
|
+
hitsPerPage: 15,
|
|
170
|
+
advancedSyntax: true,
|
|
171
|
+
disjunctiveFacets: ['language', 'docusaurus_tag'],
|
|
172
|
+
});
|
|
173
|
+
algoliaHelper.on(
|
|
174
|
+
'result',
|
|
175
|
+
({results: {query, hits, page, nbHits, nbPages}}) => {
|
|
176
|
+
if (query === '' || !(hits instanceof Array)) {
|
|
177
|
+
searchResultStateDispatcher({type: 'reset'});
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const sanitizeValue = (value) =>
|
|
181
|
+
value.replace(
|
|
182
|
+
/algolia-docsearch-suggestion--highlight/g,
|
|
183
|
+
'search-result-match',
|
|
184
|
+
);
|
|
185
|
+
const items = hits.map(
|
|
186
|
+
({
|
|
187
|
+
url,
|
|
188
|
+
_highlightResult: {hierarchy},
|
|
189
|
+
_snippetResult: snippet = {},
|
|
190
|
+
}) => {
|
|
191
|
+
const parsedURL = new URL(url);
|
|
192
|
+
const titles = Object.keys(hierarchy).map((key) =>
|
|
193
|
+
sanitizeValue(hierarchy[key].value),
|
|
194
|
+
);
|
|
195
|
+
return {
|
|
196
|
+
title: titles.pop(),
|
|
197
|
+
url: isRegexpStringMatch(externalUrlRegex, parsedURL.href)
|
|
198
|
+
? parsedURL.href
|
|
199
|
+
: parsedURL.pathname + parsedURL.hash,
|
|
200
|
+
summary: snippet.content
|
|
201
|
+
? `${sanitizeValue(snippet.content.value)}...`
|
|
202
|
+
: '',
|
|
203
|
+
breadcrumbs: titles,
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
);
|
|
207
|
+
searchResultStateDispatcher({
|
|
208
|
+
type: 'update',
|
|
209
|
+
value: {
|
|
210
|
+
items,
|
|
211
|
+
query,
|
|
212
|
+
totalResults: nbHits,
|
|
213
|
+
totalPages: nbPages,
|
|
214
|
+
lastPage: page,
|
|
215
|
+
hasMore: nbPages > page + 1,
|
|
216
|
+
loading: false,
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
);
|
|
221
|
+
const [loaderRef, setLoaderRef] = useState(null);
|
|
222
|
+
const prevY = useRef(0);
|
|
223
|
+
const observer = useRef(
|
|
224
|
+
ExecutionEnvironment.canUseDOM &&
|
|
225
|
+
new IntersectionObserver(
|
|
226
|
+
(entries) => {
|
|
227
|
+
const {
|
|
228
|
+
isIntersecting,
|
|
229
|
+
boundingClientRect: {y: currentY},
|
|
230
|
+
} = entries[0];
|
|
231
|
+
if (isIntersecting && prevY.current > currentY) {
|
|
232
|
+
searchResultStateDispatcher({type: 'advance'});
|
|
233
|
+
}
|
|
234
|
+
prevY.current = currentY;
|
|
235
|
+
},
|
|
236
|
+
{threshold: 1},
|
|
237
|
+
),
|
|
238
|
+
);
|
|
239
|
+
const getTitle = () =>
|
|
240
|
+
searchQuery
|
|
241
|
+
? translate(
|
|
242
|
+
{
|
|
161
243
|
id: 'theme.SearchPage.existingResultsTitle',
|
|
162
244
|
message: 'Search results for "{query}"',
|
|
163
245
|
description: 'The search page title for non-empty query',
|
|
164
|
-
|
|
246
|
+
},
|
|
247
|
+
{
|
|
165
248
|
query: searchQuery,
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
249
|
+
},
|
|
250
|
+
)
|
|
251
|
+
: translate({
|
|
252
|
+
id: 'theme.SearchPage.emptyResultsTitle',
|
|
253
|
+
message: 'Search the documentation',
|
|
254
|
+
description: 'The search page title for empty query',
|
|
171
255
|
});
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
256
|
+
const makeSearch = useDynamicCallback((page = 0) => {
|
|
257
|
+
algoliaHelper.addDisjunctiveFacetRefinement('docusaurus_tag', 'default');
|
|
258
|
+
algoliaHelper.addDisjunctiveFacetRefinement('language', currentLocale);
|
|
259
|
+
Object.entries(docsSearchVersionsHelpers.searchVersions).forEach(
|
|
260
|
+
([pluginId, searchVersion]) => {
|
|
261
|
+
algoliaHelper.addDisjunctiveFacetRefinement(
|
|
262
|
+
'docusaurus_tag',
|
|
263
|
+
`docs-${pluginId}-${searchVersion}`,
|
|
264
|
+
);
|
|
265
|
+
},
|
|
266
|
+
);
|
|
267
|
+
algoliaHelper.setQuery(searchQuery).setPage(page).search();
|
|
268
|
+
});
|
|
269
|
+
useEffect(() => {
|
|
270
|
+
if (!loaderRef) {
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
const currentObserver = observer.current;
|
|
274
|
+
if (currentObserver) {
|
|
275
|
+
currentObserver.observe(loaderRef);
|
|
276
|
+
return () => currentObserver.unobserve(loaderRef);
|
|
277
|
+
}
|
|
278
|
+
return () => true;
|
|
279
|
+
}, [loaderRef]);
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
searchResultStateDispatcher({type: 'reset'});
|
|
282
|
+
if (searchQuery) {
|
|
283
|
+
searchResultStateDispatcher({type: 'loading'});
|
|
284
|
+
setTimeout(() => {
|
|
285
|
+
makeSearch();
|
|
286
|
+
}, 300);
|
|
287
|
+
}
|
|
288
|
+
}, [searchQuery, docsSearchVersionsHelpers.searchVersions, makeSearch]);
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
if (!searchResultState.lastPage || searchResultState.lastPage === 0) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
makeSearch(searchResultState.lastPage);
|
|
294
|
+
}, [makeSearch, searchResultState.lastPage]);
|
|
295
|
+
return (
|
|
296
|
+
<Layout wrapperClassName="search-page-wrapper">
|
|
207
297
|
<Head>
|
|
208
298
|
<title>{useTitleFormatter(getTitle())}</title>
|
|
209
299
|
{/*
|
|
210
300
|
We should not index search pages
|
|
211
301
|
See https://github.com/facebook/docusaurus/pull/3233
|
|
212
302
|
*/}
|
|
213
|
-
<meta property="robots" content="noindex, follow"/>
|
|
303
|
+
<meta property="robots" content="noindex, follow" />
|
|
214
304
|
</Head>
|
|
215
305
|
|
|
216
306
|
<div className="container margin-vert--lg">
|
|
217
307
|
<h1>{getTitle()}</h1>
|
|
218
308
|
|
|
219
309
|
<form className="row" onSubmit={(e) => e.preventDefault()}>
|
|
220
|
-
<div
|
|
221
|
-
'col
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
310
|
+
<div
|
|
311
|
+
className={clsx('col', styles.searchQueryColumn, {
|
|
312
|
+
'col--9': docsSearchVersionsHelpers.versioningEnabled,
|
|
313
|
+
'col--12': !docsSearchVersionsHelpers.versioningEnabled,
|
|
314
|
+
})}>
|
|
315
|
+
<input
|
|
316
|
+
type="search"
|
|
317
|
+
name="q"
|
|
318
|
+
className={styles.searchQueryInput}
|
|
319
|
+
placeholder={translate({
|
|
320
|
+
id: 'theme.SearchPage.inputPlaceholder',
|
|
321
|
+
message: 'Type your search here',
|
|
322
|
+
description: 'The placeholder for search page input',
|
|
323
|
+
})}
|
|
324
|
+
aria-label={translate({
|
|
325
|
+
id: 'theme.SearchPage.inputLabel',
|
|
326
|
+
message: 'Search',
|
|
327
|
+
description: 'The ARIA label for search page input',
|
|
328
|
+
})}
|
|
329
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
330
|
+
value={searchQuery}
|
|
331
|
+
autoComplete="off"
|
|
332
|
+
autoFocus
|
|
333
|
+
/>
|
|
233
334
|
</div>
|
|
234
335
|
|
|
235
|
-
{docsSearchVersionsHelpers.versioningEnabled && (
|
|
336
|
+
{docsSearchVersionsHelpers.versioningEnabled && (
|
|
337
|
+
<SearchVersionSelectList
|
|
338
|
+
docsSearchVersionsHelpers={docsSearchVersionsHelpers}
|
|
339
|
+
/>
|
|
340
|
+
)}
|
|
236
341
|
</form>
|
|
237
342
|
|
|
238
343
|
<div className="row">
|
|
239
344
|
<div className={clsx('col', 'col--8', styles.searchResultsColumn)}>
|
|
240
345
|
{!!searchResultState.totalResults &&
|
|
241
|
-
|
|
346
|
+
documentsFoundPlural(searchResultState.totalResults)}
|
|
242
347
|
</div>
|
|
243
348
|
|
|
244
|
-
<div
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
349
|
+
<div
|
|
350
|
+
className={clsx(
|
|
351
|
+
'col',
|
|
352
|
+
'col--4',
|
|
353
|
+
'text--right',
|
|
354
|
+
styles.searchLogoColumn,
|
|
355
|
+
)}>
|
|
356
|
+
<a
|
|
357
|
+
target="_blank"
|
|
358
|
+
rel="noopener noreferrer"
|
|
359
|
+
href="https://www.algolia.com/"
|
|
360
|
+
aria-label={translate({
|
|
361
|
+
id: 'theme.SearchPage.algoliaLabel',
|
|
362
|
+
message: 'Search by Algolia',
|
|
363
|
+
description: 'The ARIA label for Algolia mention',
|
|
364
|
+
})}>
|
|
250
365
|
<svg viewBox="0 0 168 24" className={styles.algoliaLogo}>
|
|
251
366
|
<g fill="none">
|
|
252
|
-
<path
|
|
253
|
-
|
|
254
|
-
|
|
367
|
+
<path
|
|
368
|
+
className={styles.algoliaLogoPathFill}
|
|
369
|
+
d="M120.925 18.804c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199 5.7 5.7 0 0 0-.897.069 2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 0 1-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 0 1 1.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 0 1 .233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 0 0-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 0 1 1.753 1.216 5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17zM6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 0 1-.582-.271 13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z"
|
|
370
|
+
/>
|
|
371
|
+
<path
|
|
372
|
+
fill="#5468FF"
|
|
373
|
+
d="M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938z"
|
|
374
|
+
/>
|
|
375
|
+
<path
|
|
376
|
+
fill="white"
|
|
377
|
+
d="M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729 6.37 6.37 0 0 0 6.372-6.368 6.358 6.358 0 0 0-6.371-6.36"
|
|
378
|
+
/>
|
|
255
379
|
</g>
|
|
256
380
|
</svg>
|
|
257
381
|
</a>
|
|
258
382
|
</div>
|
|
259
383
|
</div>
|
|
260
384
|
|
|
261
|
-
{searchResultState.items.length > 0 ? (
|
|
262
|
-
|
|
385
|
+
{searchResultState.items.length > 0 ? (
|
|
386
|
+
<main>
|
|
387
|
+
{searchResultState.items.map(
|
|
388
|
+
({title, url, summary, breadcrumbs}, i) => (
|
|
389
|
+
<article key={i} className={styles.searchResultItem}>
|
|
263
390
|
<h2 className={styles.searchResultItemHeading}>
|
|
264
|
-
<Link to={url} dangerouslySetInnerHTML={{
|
|
391
|
+
<Link to={url} dangerouslySetInnerHTML={{__html: title}} />
|
|
265
392
|
</h2>
|
|
266
393
|
|
|
267
|
-
{breadcrumbs.length > 0 && (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
394
|
+
{breadcrumbs.length > 0 && (
|
|
395
|
+
<nav aria-label="breadcrumbs">
|
|
396
|
+
<ul
|
|
397
|
+
className={clsx(
|
|
398
|
+
'breadcrumbs',
|
|
399
|
+
styles.searchResultItemPath,
|
|
400
|
+
)}>
|
|
401
|
+
{breadcrumbs.map((html, index) => (
|
|
402
|
+
<li
|
|
403
|
+
key={index}
|
|
404
|
+
className="breadcrumbs__item"
|
|
405
|
+
// Developer provided the HTML, so assume it's safe.
|
|
406
|
+
// eslint-disable-next-line react/no-danger
|
|
407
|
+
dangerouslySetInnerHTML={{__html: html}}
|
|
408
|
+
/>
|
|
409
|
+
))}
|
|
273
410
|
</ul>
|
|
274
|
-
</nav>
|
|
411
|
+
</nav>
|
|
412
|
+
)}
|
|
275
413
|
|
|
276
|
-
{summary && (
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
414
|
+
{summary && (
|
|
415
|
+
<p
|
|
416
|
+
className={styles.searchResultItemSummary}
|
|
417
|
+
// Developer provided the HTML, so assume it's safe.
|
|
418
|
+
// eslint-disable-next-line react/no-danger
|
|
419
|
+
dangerouslySetInnerHTML={{__html: summary}}
|
|
420
|
+
/>
|
|
421
|
+
)}
|
|
422
|
+
</article>
|
|
423
|
+
),
|
|
424
|
+
)}
|
|
425
|
+
</main>
|
|
426
|
+
) : (
|
|
427
|
+
[
|
|
428
|
+
searchQuery && !searchResultState.loading && (
|
|
429
|
+
<p key="no-results">
|
|
430
|
+
<Translate
|
|
431
|
+
id="theme.SearchPage.noResultsText"
|
|
432
|
+
description="The paragraph for empty search result">
|
|
284
433
|
No results were found
|
|
285
434
|
</Translate>
|
|
286
|
-
</p>
|
|
287
|
-
|
|
288
|
-
|
|
435
|
+
</p>
|
|
436
|
+
),
|
|
437
|
+
!!searchResultState.loading && (
|
|
438
|
+
<div key="spinner" className={styles.loadingSpinner} />
|
|
439
|
+
),
|
|
440
|
+
]
|
|
441
|
+
)}
|
|
289
442
|
|
|
290
|
-
{searchResultState.hasMore && (
|
|
291
|
-
|
|
443
|
+
{searchResultState.hasMore && (
|
|
444
|
+
<div className={styles.loader} ref={setLoaderRef}>
|
|
445
|
+
<Translate
|
|
446
|
+
id="theme.SearchPage.fetchingNewResults"
|
|
447
|
+
description="The paragraph for fetching new search results">
|
|
292
448
|
Fetching new results...
|
|
293
449
|
</Translate>
|
|
294
|
-
</div>
|
|
450
|
+
</div>
|
|
451
|
+
)}
|
|
295
452
|
</div>
|
|
296
|
-
</Layout>
|
|
453
|
+
</Layout>
|
|
454
|
+
);
|
|
297
455
|
}
|
|
298
|
-
export default SearchPage;
|