@docusaurus/theme-search-algolia 2.0.0-beta.15d451942 → 2.0.0-beta.18
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.d.ts +7 -0
- package/lib/client/index.js +7 -0
- package/lib/client/useAlgoliaContextualFacetFilters.d.ts +7 -0
- package/lib/client/useAlgoliaContextualFacetFilters.js +15 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +107 -0
- package/lib/templates/opensearch.d.ts +8 -0
- package/lib/templates/opensearch.js +23 -0
- package/lib/theme/SearchBar/index.d.ts +8 -0
- package/{src → lib}/theme/SearchBar/index.js +45 -50
- package/lib/theme/SearchBar/styles.css +21 -0
- package/lib/theme/SearchBar/styles.module.css +20 -0
- package/lib/theme/SearchPage/index.d.ts +8 -0
- package/{src → lib}/theme/SearchPage/index.js +95 -128
- package/lib/theme/SearchPage/styles.module.css +119 -0
- package/lib/validateThemeConfig.d.ts +15 -0
- package/lib/validateThemeConfig.js +50 -0
- package/package.json +34 -13
- package/src/client/index.ts +8 -0
- package/src/{theme/hooks/useAlgoliaContextualFacetFilters.js → client/useAlgoliaContextualFacetFilters.ts} +3 -3
- package/src/deps.d.ts +10 -0
- package/src/index.ts +116 -0
- package/src/templates/{opensearch.js → opensearch.ts} +7 -5
- package/src/theme/SearchBar/index.tsx +276 -0
- package/src/theme/SearchPage/index.tsx +528 -0
- package/src/theme/SearchPage/styles.module.css +15 -34
- package/src/theme-search-algolia.d.ts +35 -0
- package/src/types.d.ts +10 -0
- package/src/validateThemeConfig.ts +53 -0
- package/src/__tests__/validateThemeConfig.test.js +0 -121
- package/src/index.js +0 -92
- package/src/theme/SearchMetadatas/index.js +0 -25
- package/src/theme/hooks/useSearchQuery.js +0 -44
- package/src/validateThemeConfig.js +0 -45
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/* eslint-disable jsx-a11y/no-autofocus */
|
|
9
|
+
|
|
10
|
+
import React, {useEffect, useState, useReducer, useRef} from 'react';
|
|
11
|
+
|
|
12
|
+
import algoliaSearch from 'algoliasearch/lite';
|
|
13
|
+
import algoliaSearchHelper from 'algoliasearch-helper';
|
|
14
|
+
import clsx from 'clsx';
|
|
15
|
+
|
|
16
|
+
import Head from '@docusaurus/Head';
|
|
17
|
+
import Link from '@docusaurus/Link';
|
|
18
|
+
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
19
|
+
import {
|
|
20
|
+
HtmlClassNameProvider,
|
|
21
|
+
useTitleFormatter,
|
|
22
|
+
usePluralForm,
|
|
23
|
+
isRegexpStringMatch,
|
|
24
|
+
useDynamicCallback,
|
|
25
|
+
useSearchPage,
|
|
26
|
+
} from '@docusaurus/theme-common';
|
|
27
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
28
|
+
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
29
|
+
import Layout from '@theme/Layout';
|
|
30
|
+
import Translate, {translate} from '@docusaurus/Translate';
|
|
31
|
+
import styles from './styles.module.css';
|
|
32
|
+
import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
|
|
33
|
+
|
|
34
|
+
// Very simple pluralization: probably good enough for now
|
|
35
|
+
function useDocumentsFoundPlural() {
|
|
36
|
+
const {selectMessage} = usePluralForm();
|
|
37
|
+
return (count: number) =>
|
|
38
|
+
selectMessage(
|
|
39
|
+
count,
|
|
40
|
+
translate(
|
|
41
|
+
{
|
|
42
|
+
id: 'theme.SearchPage.documentsFound.plurals',
|
|
43
|
+
description:
|
|
44
|
+
'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)',
|
|
45
|
+
message: 'One document found|{count} documents found',
|
|
46
|
+
},
|
|
47
|
+
{count},
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function useDocsSearchVersionsHelpers() {
|
|
53
|
+
const allDocsData = useAllDocsData();
|
|
54
|
+
|
|
55
|
+
// State of the version select menus / algolia facet filters
|
|
56
|
+
// docsPluginId -> versionName map
|
|
57
|
+
const [searchVersions, setSearchVersions] = useState<{
|
|
58
|
+
[pluginId: string]: string;
|
|
59
|
+
}>(() =>
|
|
60
|
+
Object.entries(allDocsData).reduce(
|
|
61
|
+
(acc, [pluginId, pluginData]) => ({
|
|
62
|
+
...acc,
|
|
63
|
+
[pluginId]: pluginData.versions[0]!.name,
|
|
64
|
+
}),
|
|
65
|
+
{},
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Set the value of a single select menu
|
|
70
|
+
const setSearchVersion = (pluginId: string, searchVersion: string) =>
|
|
71
|
+
setSearchVersions((s) => ({...s, [pluginId]: searchVersion}));
|
|
72
|
+
|
|
73
|
+
const versioningEnabled = Object.values(allDocsData).some(
|
|
74
|
+
(docsData) => docsData.versions.length > 1,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
allDocsData,
|
|
79
|
+
versioningEnabled,
|
|
80
|
+
searchVersions,
|
|
81
|
+
setSearchVersion,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// We want to display one select per versioned docs plugin instance
|
|
86
|
+
function SearchVersionSelectList({
|
|
87
|
+
docsSearchVersionsHelpers,
|
|
88
|
+
}: {
|
|
89
|
+
docsSearchVersionsHelpers: ReturnType<typeof useDocsSearchVersionsHelpers>;
|
|
90
|
+
}) {
|
|
91
|
+
const versionedPluginEntries = Object.entries(
|
|
92
|
+
docsSearchVersionsHelpers.allDocsData,
|
|
93
|
+
)
|
|
94
|
+
// Do not show a version select for unversioned docs plugin instances
|
|
95
|
+
.filter(([, docsData]) => docsData.versions.length > 1);
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<div
|
|
99
|
+
className={clsx(
|
|
100
|
+
'col',
|
|
101
|
+
'col--3',
|
|
102
|
+
'padding-left--none',
|
|
103
|
+
styles.searchVersionColumn,
|
|
104
|
+
)}>
|
|
105
|
+
{versionedPluginEntries.map(([pluginId, docsData]) => {
|
|
106
|
+
const labelPrefix =
|
|
107
|
+
versionedPluginEntries.length > 1 ? `${pluginId}: ` : '';
|
|
108
|
+
return (
|
|
109
|
+
<select
|
|
110
|
+
key={pluginId}
|
|
111
|
+
onChange={(e) =>
|
|
112
|
+
docsSearchVersionsHelpers.setSearchVersion(
|
|
113
|
+
pluginId,
|
|
114
|
+
e.target.value,
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
defaultValue={docsSearchVersionsHelpers.searchVersions[pluginId]}
|
|
118
|
+
className={styles.searchVersionInput}>
|
|
119
|
+
{docsData.versions.map((version, i) => (
|
|
120
|
+
<option
|
|
121
|
+
key={i}
|
|
122
|
+
label={`${labelPrefix}${version.label}`}
|
|
123
|
+
value={version.name}
|
|
124
|
+
/>
|
|
125
|
+
))}
|
|
126
|
+
</select>
|
|
127
|
+
);
|
|
128
|
+
})}
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
type ResultDispatcherState = {
|
|
134
|
+
items: {
|
|
135
|
+
title: string;
|
|
136
|
+
url: string;
|
|
137
|
+
summary: string;
|
|
138
|
+
breadcrumbs: string[];
|
|
139
|
+
}[];
|
|
140
|
+
query: string | null;
|
|
141
|
+
totalResults: number | null;
|
|
142
|
+
totalPages: number | null;
|
|
143
|
+
lastPage: number | null;
|
|
144
|
+
hasMore: boolean | null;
|
|
145
|
+
loading: boolean | null;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
type ResultDispatcher =
|
|
149
|
+
| {type: 'reset'; value?: undefined}
|
|
150
|
+
| {type: 'loading'; value?: undefined}
|
|
151
|
+
| {type: 'update'; value: ResultDispatcherState}
|
|
152
|
+
| {type: 'advance'; value?: undefined};
|
|
153
|
+
|
|
154
|
+
function SearchPageContent(): JSX.Element {
|
|
155
|
+
const {
|
|
156
|
+
siteConfig: {themeConfig},
|
|
157
|
+
i18n: {currentLocale},
|
|
158
|
+
} = useDocusaurusContext();
|
|
159
|
+
const {
|
|
160
|
+
algolia: {appId, apiKey, indexName, externalUrlRegex},
|
|
161
|
+
} = themeConfig as ThemeConfig;
|
|
162
|
+
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
163
|
+
|
|
164
|
+
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
165
|
+
const {searchQuery, setSearchQuery} = useSearchPage();
|
|
166
|
+
const initialSearchResultState: ResultDispatcherState = {
|
|
167
|
+
items: [],
|
|
168
|
+
query: null,
|
|
169
|
+
totalResults: null,
|
|
170
|
+
totalPages: null,
|
|
171
|
+
lastPage: null,
|
|
172
|
+
hasMore: null,
|
|
173
|
+
loading: null,
|
|
174
|
+
};
|
|
175
|
+
const [searchResultState, searchResultStateDispatcher] = useReducer(
|
|
176
|
+
(prevState: ResultDispatcherState, data: ResultDispatcher) => {
|
|
177
|
+
switch (data.type) {
|
|
178
|
+
case 'reset': {
|
|
179
|
+
return initialSearchResultState;
|
|
180
|
+
}
|
|
181
|
+
case 'loading': {
|
|
182
|
+
return {...prevState, loading: true};
|
|
183
|
+
}
|
|
184
|
+
case 'update': {
|
|
185
|
+
if (searchQuery !== data.value.query) {
|
|
186
|
+
return prevState;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
...data.value,
|
|
191
|
+
items:
|
|
192
|
+
data.value.lastPage === 0
|
|
193
|
+
? data.value.items
|
|
194
|
+
: prevState.items.concat(data.value.items),
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
case 'advance': {
|
|
198
|
+
const hasMore = prevState.totalPages! > prevState.lastPage! + 1;
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
...prevState,
|
|
202
|
+
lastPage: hasMore ? prevState.lastPage! + 1 : prevState.lastPage,
|
|
203
|
+
hasMore,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
default:
|
|
207
|
+
return prevState;
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
initialSearchResultState,
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
const algoliaClient = algoliaSearch(appId, apiKey);
|
|
214
|
+
const algoliaHelper = algoliaSearchHelper(algoliaClient, indexName, {
|
|
215
|
+
hitsPerPage: 15,
|
|
216
|
+
advancedSyntax: true,
|
|
217
|
+
disjunctiveFacets: ['language', 'docusaurus_tag'],
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
algoliaHelper.on(
|
|
221
|
+
'result',
|
|
222
|
+
({results: {query, hits, page, nbHits, nbPages}}) => {
|
|
223
|
+
if (query === '' || !Array.isArray(hits)) {
|
|
224
|
+
searchResultStateDispatcher({type: 'reset'});
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const sanitizeValue = (value: string) =>
|
|
229
|
+
value.replace(
|
|
230
|
+
/algolia-docsearch-suggestion--highlight/g,
|
|
231
|
+
'search-result-match',
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const items = hits.map(
|
|
235
|
+
({
|
|
236
|
+
url,
|
|
237
|
+
_highlightResult: {hierarchy},
|
|
238
|
+
_snippetResult: snippet = {},
|
|
239
|
+
}) => {
|
|
240
|
+
const parsedURL = new URL(url);
|
|
241
|
+
const titles = Object.keys(hierarchy).map((key) =>
|
|
242
|
+
sanitizeValue(hierarchy[key].value),
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
title: titles.pop()!,
|
|
247
|
+
url: isRegexpStringMatch(externalUrlRegex, parsedURL.href)
|
|
248
|
+
? parsedURL.href
|
|
249
|
+
: parsedURL.pathname + parsedURL.hash,
|
|
250
|
+
summary: snippet.content
|
|
251
|
+
? `${sanitizeValue(snippet.content.value)}...`
|
|
252
|
+
: '',
|
|
253
|
+
breadcrumbs: titles,
|
|
254
|
+
};
|
|
255
|
+
},
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
searchResultStateDispatcher({
|
|
259
|
+
type: 'update',
|
|
260
|
+
value: {
|
|
261
|
+
items,
|
|
262
|
+
query,
|
|
263
|
+
totalResults: nbHits,
|
|
264
|
+
totalPages: nbPages,
|
|
265
|
+
lastPage: page,
|
|
266
|
+
hasMore: nbPages > page + 1,
|
|
267
|
+
loading: false,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const [loaderRef, setLoaderRef] = useState<HTMLDivElement | null>(null);
|
|
274
|
+
const prevY = useRef(0);
|
|
275
|
+
const observer = useRef(
|
|
276
|
+
ExecutionEnvironment.canUseDOM &&
|
|
277
|
+
new IntersectionObserver(
|
|
278
|
+
(entries) => {
|
|
279
|
+
const {
|
|
280
|
+
isIntersecting,
|
|
281
|
+
boundingClientRect: {y: currentY},
|
|
282
|
+
} = entries[0]!;
|
|
283
|
+
|
|
284
|
+
if (isIntersecting && prevY.current > currentY) {
|
|
285
|
+
searchResultStateDispatcher({type: 'advance'});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
prevY.current = currentY;
|
|
289
|
+
},
|
|
290
|
+
{threshold: 1},
|
|
291
|
+
),
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
const getTitle = () =>
|
|
295
|
+
searchQuery
|
|
296
|
+
? translate(
|
|
297
|
+
{
|
|
298
|
+
id: 'theme.SearchPage.existingResultsTitle',
|
|
299
|
+
message: 'Search results for "{query}"',
|
|
300
|
+
description: 'The search page title for non-empty query',
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
query: searchQuery,
|
|
304
|
+
},
|
|
305
|
+
)
|
|
306
|
+
: translate({
|
|
307
|
+
id: 'theme.SearchPage.emptyResultsTitle',
|
|
308
|
+
message: 'Search the documentation',
|
|
309
|
+
description: 'The search page title for empty query',
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const makeSearch = useDynamicCallback((page: number = 0) => {
|
|
313
|
+
algoliaHelper.addDisjunctiveFacetRefinement('docusaurus_tag', 'default');
|
|
314
|
+
algoliaHelper.addDisjunctiveFacetRefinement('language', currentLocale);
|
|
315
|
+
|
|
316
|
+
Object.entries(docsSearchVersionsHelpers.searchVersions).forEach(
|
|
317
|
+
([pluginId, searchVersion]) => {
|
|
318
|
+
algoliaHelper.addDisjunctiveFacetRefinement(
|
|
319
|
+
'docusaurus_tag',
|
|
320
|
+
`docs-${pluginId}-${searchVersion}`,
|
|
321
|
+
);
|
|
322
|
+
},
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
algoliaHelper.setQuery(searchQuery).setPage(page).search();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
useEffect(() => {
|
|
329
|
+
if (!loaderRef) {
|
|
330
|
+
return undefined;
|
|
331
|
+
}
|
|
332
|
+
const currentObserver = observer.current;
|
|
333
|
+
if (currentObserver) {
|
|
334
|
+
currentObserver.observe(loaderRef);
|
|
335
|
+
return () => currentObserver.unobserve(loaderRef);
|
|
336
|
+
}
|
|
337
|
+
return () => true;
|
|
338
|
+
}, [loaderRef]);
|
|
339
|
+
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
searchResultStateDispatcher({type: 'reset'});
|
|
342
|
+
|
|
343
|
+
if (searchQuery) {
|
|
344
|
+
searchResultStateDispatcher({type: 'loading'});
|
|
345
|
+
|
|
346
|
+
setTimeout(() => {
|
|
347
|
+
makeSearch();
|
|
348
|
+
}, 300);
|
|
349
|
+
}
|
|
350
|
+
}, [searchQuery, docsSearchVersionsHelpers.searchVersions, makeSearch]);
|
|
351
|
+
|
|
352
|
+
useEffect(() => {
|
|
353
|
+
if (!searchResultState.lastPage || searchResultState.lastPage === 0) {
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
makeSearch(searchResultState.lastPage);
|
|
358
|
+
}, [makeSearch, searchResultState.lastPage]);
|
|
359
|
+
|
|
360
|
+
return (
|
|
361
|
+
<Layout>
|
|
362
|
+
<Head>
|
|
363
|
+
<title>{useTitleFormatter(getTitle())}</title>
|
|
364
|
+
{/*
|
|
365
|
+
We should not index search pages
|
|
366
|
+
See https://github.com/facebook/docusaurus/pull/3233
|
|
367
|
+
*/}
|
|
368
|
+
<meta property="robots" content="noindex, follow" />
|
|
369
|
+
</Head>
|
|
370
|
+
|
|
371
|
+
<div className="container margin-vert--lg">
|
|
372
|
+
<h1>{getTitle()}</h1>
|
|
373
|
+
|
|
374
|
+
<form className="row" onSubmit={(e) => e.preventDefault()}>
|
|
375
|
+
<div
|
|
376
|
+
className={clsx('col', styles.searchQueryColumn, {
|
|
377
|
+
'col--9': docsSearchVersionsHelpers.versioningEnabled,
|
|
378
|
+
'col--12': !docsSearchVersionsHelpers.versioningEnabled,
|
|
379
|
+
})}>
|
|
380
|
+
<input
|
|
381
|
+
type="search"
|
|
382
|
+
name="q"
|
|
383
|
+
className={styles.searchQueryInput}
|
|
384
|
+
placeholder={translate({
|
|
385
|
+
id: 'theme.SearchPage.inputPlaceholder',
|
|
386
|
+
message: 'Type your search here',
|
|
387
|
+
description: 'The placeholder for search page input',
|
|
388
|
+
})}
|
|
389
|
+
aria-label={translate({
|
|
390
|
+
id: 'theme.SearchPage.inputLabel',
|
|
391
|
+
message: 'Search',
|
|
392
|
+
description: 'The ARIA label for search page input',
|
|
393
|
+
})}
|
|
394
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
395
|
+
value={searchQuery}
|
|
396
|
+
autoComplete="off"
|
|
397
|
+
autoFocus
|
|
398
|
+
/>
|
|
399
|
+
</div>
|
|
400
|
+
|
|
401
|
+
{docsSearchVersionsHelpers.versioningEnabled && (
|
|
402
|
+
<SearchVersionSelectList
|
|
403
|
+
docsSearchVersionsHelpers={docsSearchVersionsHelpers}
|
|
404
|
+
/>
|
|
405
|
+
)}
|
|
406
|
+
</form>
|
|
407
|
+
|
|
408
|
+
<div className="row">
|
|
409
|
+
<div className={clsx('col', 'col--8', styles.searchResultsColumn)}>
|
|
410
|
+
{!!searchResultState.totalResults &&
|
|
411
|
+
documentsFoundPlural(searchResultState.totalResults)}
|
|
412
|
+
</div>
|
|
413
|
+
|
|
414
|
+
<div
|
|
415
|
+
className={clsx(
|
|
416
|
+
'col',
|
|
417
|
+
'col--4',
|
|
418
|
+
'text--right',
|
|
419
|
+
styles.searchLogoColumn,
|
|
420
|
+
)}>
|
|
421
|
+
<a
|
|
422
|
+
target="_blank"
|
|
423
|
+
rel="noopener noreferrer"
|
|
424
|
+
href="https://www.algolia.com/"
|
|
425
|
+
aria-label={translate({
|
|
426
|
+
id: 'theme.SearchPage.algoliaLabel',
|
|
427
|
+
message: 'Search by Algolia',
|
|
428
|
+
description: 'The ARIA label for Algolia mention',
|
|
429
|
+
})}>
|
|
430
|
+
<svg viewBox="0 0 168 24" className={styles.algoliaLogo}>
|
|
431
|
+
<g fill="none">
|
|
432
|
+
<path
|
|
433
|
+
className={styles.algoliaLogoPathFill}
|
|
434
|
+
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"
|
|
435
|
+
/>
|
|
436
|
+
<path
|
|
437
|
+
fill="#5468FF"
|
|
438
|
+
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"
|
|
439
|
+
/>
|
|
440
|
+
<path
|
|
441
|
+
fill="white"
|
|
442
|
+
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"
|
|
443
|
+
/>
|
|
444
|
+
</g>
|
|
445
|
+
</svg>
|
|
446
|
+
</a>
|
|
447
|
+
</div>
|
|
448
|
+
</div>
|
|
449
|
+
|
|
450
|
+
{searchResultState.items.length > 0 ? (
|
|
451
|
+
<main>
|
|
452
|
+
{searchResultState.items.map(
|
|
453
|
+
({title, url, summary, breadcrumbs}, i) => (
|
|
454
|
+
<article key={i} className={styles.searchResultItem}>
|
|
455
|
+
<h2 className={styles.searchResultItemHeading}>
|
|
456
|
+
<Link to={url} dangerouslySetInnerHTML={{__html: title}} />
|
|
457
|
+
</h2>
|
|
458
|
+
|
|
459
|
+
{breadcrumbs.length > 0 && (
|
|
460
|
+
<nav aria-label="breadcrumbs">
|
|
461
|
+
<ul
|
|
462
|
+
className={clsx(
|
|
463
|
+
'breadcrumbs',
|
|
464
|
+
styles.searchResultItemPath,
|
|
465
|
+
)}>
|
|
466
|
+
{breadcrumbs.map((html, index) => (
|
|
467
|
+
<li
|
|
468
|
+
key={index}
|
|
469
|
+
className="breadcrumbs__item"
|
|
470
|
+
// Developer provided the HTML, so assume it's safe.
|
|
471
|
+
// eslint-disable-next-line react/no-danger
|
|
472
|
+
dangerouslySetInnerHTML={{__html: html}}
|
|
473
|
+
/>
|
|
474
|
+
))}
|
|
475
|
+
</ul>
|
|
476
|
+
</nav>
|
|
477
|
+
)}
|
|
478
|
+
|
|
479
|
+
{summary && (
|
|
480
|
+
<p
|
|
481
|
+
className={styles.searchResultItemSummary}
|
|
482
|
+
// Developer provided the HTML, so assume it's safe.
|
|
483
|
+
// eslint-disable-next-line react/no-danger
|
|
484
|
+
dangerouslySetInnerHTML={{__html: summary}}
|
|
485
|
+
/>
|
|
486
|
+
)}
|
|
487
|
+
</article>
|
|
488
|
+
),
|
|
489
|
+
)}
|
|
490
|
+
</main>
|
|
491
|
+
) : (
|
|
492
|
+
[
|
|
493
|
+
searchQuery && !searchResultState.loading && (
|
|
494
|
+
<p key="no-results">
|
|
495
|
+
<Translate
|
|
496
|
+
id="theme.SearchPage.noResultsText"
|
|
497
|
+
description="The paragraph for empty search result">
|
|
498
|
+
No results were found
|
|
499
|
+
</Translate>
|
|
500
|
+
</p>
|
|
501
|
+
),
|
|
502
|
+
!!searchResultState.loading && (
|
|
503
|
+
<div key="spinner" className={styles.loadingSpinner} />
|
|
504
|
+
),
|
|
505
|
+
]
|
|
506
|
+
)}
|
|
507
|
+
|
|
508
|
+
{searchResultState.hasMore && (
|
|
509
|
+
<div className={styles.loader} ref={setLoaderRef}>
|
|
510
|
+
<Translate
|
|
511
|
+
id="theme.SearchPage.fetchingNewResults"
|
|
512
|
+
description="The paragraph for fetching new search results">
|
|
513
|
+
Fetching new results...
|
|
514
|
+
</Translate>
|
|
515
|
+
</div>
|
|
516
|
+
)}
|
|
517
|
+
</div>
|
|
518
|
+
</Layout>
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export default function SearchPage(): JSX.Element {
|
|
523
|
+
return (
|
|
524
|
+
<HtmlClassNameProvider className="search-page-wrapper">
|
|
525
|
+
<SearchPageContent />
|
|
526
|
+
</HtmlClassNameProvider>
|
|
527
|
+
);
|
|
528
|
+
}
|
|
@@ -8,23 +8,20 @@
|
|
|
8
8
|
.searchQueryInput,
|
|
9
9
|
.searchVersionInput {
|
|
10
10
|
border-radius: var(--ifm-global-radius);
|
|
11
|
-
border:
|
|
12
|
-
font
|
|
13
|
-
font-family: var(--ifm-font-family-base);
|
|
11
|
+
border: 2px solid var(--ifm-toc-border-color);
|
|
12
|
+
font: var(--ifm-font-size-base) var(--ifm-font-family-base);
|
|
14
13
|
padding: 0.8rem;
|
|
15
14
|
width: 100%;
|
|
16
15
|
background: var(--docsearch-searchbox-focus-background);
|
|
17
16
|
color: var(--docsearch-text-color);
|
|
18
|
-
margin-bottom:
|
|
19
|
-
|
|
20
|
-
transition: var(--ifm-transition-fast) ease box-shadow;
|
|
17
|
+
margin-bottom: 0.5rem;
|
|
18
|
+
transition: border var(--ifm-transition-fast) ease;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
.searchQueryInput:active,
|
|
24
21
|
.searchQueryInput:focus,
|
|
25
|
-
.searchVersionInput:active,
|
|
26
22
|
.searchVersionInput:focus {
|
|
27
|
-
|
|
23
|
+
border-color: var(--docsearch-primary-color);
|
|
24
|
+
outline: none;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
.searchQueryInput::placeholder {
|
|
@@ -33,10 +30,7 @@
|
|
|
33
30
|
|
|
34
31
|
.searchResultsColumn {
|
|
35
32
|
font-size: 0.9rem;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
.searchLogoColumn {
|
|
39
|
-
text-align: right;
|
|
33
|
+
font-weight: bold;
|
|
40
34
|
}
|
|
41
35
|
|
|
42
36
|
.algoliaLogo {
|
|
@@ -53,24 +47,18 @@
|
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
.searchResultItemHeading {
|
|
56
|
-
font-
|
|
50
|
+
font-weight: 400;
|
|
51
|
+
margin-bottom: 0;
|
|
57
52
|
}
|
|
58
53
|
|
|
59
54
|
.searchResultItemPath {
|
|
60
55
|
font-size: 0.8rem;
|
|
61
56
|
color: var(--ifm-color-content-secondary);
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.searchResultItemPathSeparator {
|
|
66
|
-
margin: 0 0.5rem;
|
|
67
|
-
font-size: 1rem;
|
|
68
|
-
font-weight: 600;
|
|
69
|
-
color: var(--ifm-color-emphasis-400);
|
|
57
|
+
--ifm-breadcrumb-separator-size-multiplier: 1;
|
|
70
58
|
}
|
|
71
59
|
|
|
72
60
|
.searchResultItemSummary {
|
|
73
|
-
margin: 0.5rem 0 0
|
|
61
|
+
margin: 0.5rem 0 0;
|
|
74
62
|
font-style: italic;
|
|
75
63
|
}
|
|
76
64
|
|
|
@@ -83,16 +71,11 @@
|
|
|
83
71
|
max-width: 40% !important;
|
|
84
72
|
}
|
|
85
73
|
|
|
86
|
-
.algoliaLogo {
|
|
87
|
-
width: 100%;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
74
|
.searchResultsColumn {
|
|
91
75
|
max-width: 60% !important;
|
|
92
76
|
}
|
|
93
77
|
|
|
94
78
|
.searchLogoColumn {
|
|
95
|
-
overflow: hidden;
|
|
96
79
|
max-width: 40% !important;
|
|
97
80
|
padding-left: 0 !important;
|
|
98
81
|
}
|
|
@@ -110,18 +93,16 @@
|
|
|
110
93
|
}
|
|
111
94
|
|
|
112
95
|
.loadingSpinner {
|
|
113
|
-
pointer-events: none;
|
|
114
96
|
width: 3rem;
|
|
115
97
|
height: 3rem;
|
|
116
|
-
border: 0.4em solid
|
|
117
|
-
border-color: #eee;
|
|
98
|
+
border: 0.4em solid #eee;
|
|
118
99
|
border-top-color: var(--ifm-color-primary);
|
|
119
100
|
border-radius: 50%;
|
|
120
|
-
animation:
|
|
101
|
+
animation: loading-spin 1s linear infinite;
|
|
121
102
|
margin: 0 auto;
|
|
122
103
|
}
|
|
123
104
|
|
|
124
|
-
@keyframes
|
|
105
|
+
@keyframes loading-spin {
|
|
125
106
|
100% {
|
|
126
107
|
transform: rotate(360deg);
|
|
127
108
|
}
|
|
@@ -133,6 +114,6 @@
|
|
|
133
114
|
|
|
134
115
|
:global(.search-result-match) {
|
|
135
116
|
color: var(--docsearch-hit-color);
|
|
136
|
-
background:
|
|
117
|
+
background: rgb(255 215 142 / 25%);
|
|
137
118
|
padding: 0.09em 0;
|
|
138
119
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
declare module '@docusaurus/theme-search-algolia' {
|
|
9
|
+
import type {DeepPartial} from 'utility-types';
|
|
10
|
+
|
|
11
|
+
export type ThemeConfig = {
|
|
12
|
+
algolia: {
|
|
13
|
+
contextualSearch: boolean;
|
|
14
|
+
externalUrlRegex?: string;
|
|
15
|
+
appId: string;
|
|
16
|
+
apiKey: string;
|
|
17
|
+
indexName: string;
|
|
18
|
+
searchParameters: {[key: string]: unknown};
|
|
19
|
+
searchPagePath: string | false | null;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type UserThemeConfig = DeepPartial<ThemeConfig>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare module '@docusaurus/theme-search-algolia/client' {
|
|
26
|
+
export function useAlgoliaContextualFacetFilters(): [string, string[]];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare module '@theme/SearchPage' {
|
|
30
|
+
export default function SearchPage(): JSX.Element;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare module '@theme/SearchBar' {
|
|
34
|
+
export default function SearchBar(): JSX.Element;
|
|
35
|
+
}
|
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/// <reference types="@docusaurus/module-type-aliases" />
|
|
9
|
+
/// <reference types="@docusaurus/theme-common" />
|
|
10
|
+
/// <reference types="@docusaurus/theme-classic" />
|