@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
package/lib/client/index.js
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
export {
|
|
7
|
+
export {useAlgoliaContextualFacetFilters} from './useAlgoliaContextualFacetFilters';
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import {useContextualSearchFilters} from '@docusaurus/theme-common';
|
|
8
8
|
// Translate search-engine agnostic search filters to Algolia search filters
|
|
9
9
|
export function useAlgoliaContextualFacetFilters() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const {locale, tags} = useContextualSearchFilters();
|
|
11
|
+
// seems safe to convert locale->language, see AlgoliaSearchMetadata comment
|
|
12
|
+
const languageFilter = `language:${locale}`;
|
|
13
|
+
const tagsFilter = tags.map((tag) => `docusaurus_tag:${tag}`);
|
|
14
|
+
return [languageFilter, tagsFilter];
|
|
15
15
|
}
|
package/lib/index.js
CHANGED
|
@@ -1,80 +1,109 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
/**
|
|
3
3
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
-
Object.defineProperty(exports,
|
|
8
|
+
Object.defineProperty(exports, '__esModule', {value: true});
|
|
9
9
|
exports.validateThemeConfig = void 0;
|
|
10
|
-
const tslib_1 = require(
|
|
11
|
-
const path_1 = (0, tslib_1.__importDefault)(require(
|
|
12
|
-
const
|
|
13
|
-
const eta_1 = require(
|
|
14
|
-
const utils_1 = require(
|
|
15
|
-
const theme_translations_1 = require(
|
|
16
|
-
const logger_1 = (0, tslib_1.__importDefault)(require(
|
|
17
|
-
const opensearch_1 = (0, tslib_1.__importDefault)(
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
const tslib_1 = require('tslib');
|
|
11
|
+
const path_1 = (0, tslib_1.__importDefault)(require('path'));
|
|
12
|
+
const fs_extra_1 = (0, tslib_1.__importDefault)(require('fs-extra'));
|
|
13
|
+
const eta_1 = require('eta');
|
|
14
|
+
const utils_1 = require('@docusaurus/utils');
|
|
15
|
+
const theme_translations_1 = require('@docusaurus/theme-translations');
|
|
16
|
+
const logger_1 = (0, tslib_1.__importDefault)(require('@docusaurus/logger'));
|
|
17
|
+
const opensearch_1 = (0, tslib_1.__importDefault)(
|
|
18
|
+
require('./templates/opensearch'),
|
|
19
|
+
);
|
|
20
|
+
const lodash_1 = (0, tslib_1.__importDefault)(require('lodash'));
|
|
21
|
+
const getCompiledOpenSearchTemplate = lodash_1.default.memoize(() =>
|
|
22
|
+
(0, eta_1.compile)(opensearch_1.default.trim()),
|
|
23
|
+
);
|
|
20
24
|
function renderOpenSearchTemplate(data) {
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
const compiled = getCompiledOpenSearchTemplate();
|
|
26
|
+
return compiled(data, eta_1.defaultConfig);
|
|
23
27
|
}
|
|
24
28
|
const OPEN_SEARCH_FILENAME = 'opensearch.xml';
|
|
25
29
|
function themeSearchAlgolia(context) {
|
|
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
|
-
|
|
30
|
+
const {
|
|
31
|
+
baseUrl,
|
|
32
|
+
siteConfig: {title, url, favicon, themeConfig},
|
|
33
|
+
i18n: {currentLocale},
|
|
34
|
+
} = context;
|
|
35
|
+
const {
|
|
36
|
+
algolia: {searchPagePath},
|
|
37
|
+
} = themeConfig;
|
|
38
|
+
return {
|
|
39
|
+
name: 'docusaurus-theme-search-algolia',
|
|
40
|
+
getThemePath() {
|
|
41
|
+
return path_1.default.resolve(__dirname, '../lib/theme');
|
|
42
|
+
},
|
|
43
|
+
getTypeScriptThemePath() {
|
|
44
|
+
return path_1.default.resolve(__dirname, '../src/theme');
|
|
45
|
+
},
|
|
46
|
+
getDefaultCodeTranslationMessages() {
|
|
47
|
+
return (0, theme_translations_1.readDefaultCodeTranslationMessages)({
|
|
48
|
+
locale: currentLocale,
|
|
49
|
+
name: 'theme-search-algolia',
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
async contentLoaded({actions: {addRoute}}) {
|
|
53
|
+
if (searchPagePath) {
|
|
54
|
+
addRoute({
|
|
55
|
+
path: (0, utils_1.normalizeUrl)([baseUrl, searchPagePath]),
|
|
56
|
+
component: '@theme/SearchPage',
|
|
57
|
+
exact: true,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
async postBuild({outDir}) {
|
|
62
|
+
if (searchPagePath) {
|
|
63
|
+
const siteUrl = (0, utils_1.normalizeUrl)([url, baseUrl]);
|
|
64
|
+
try {
|
|
65
|
+
await fs_extra_1.default.writeFile(
|
|
66
|
+
path_1.default.join(outDir, OPEN_SEARCH_FILENAME),
|
|
67
|
+
renderOpenSearchTemplate({
|
|
68
|
+
title,
|
|
69
|
+
siteUrl,
|
|
70
|
+
searchUrl: (0, utils_1.normalizeUrl)([siteUrl, searchPagePath]),
|
|
71
|
+
faviconUrl: favicon
|
|
72
|
+
? (0, utils_1.normalizeUrl)([siteUrl, favicon])
|
|
73
|
+
: null,
|
|
74
|
+
}),
|
|
75
|
+
);
|
|
76
|
+
} catch (err) {
|
|
77
|
+
logger_1.default.error('Generating OpenSearch file failed.');
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
injectHtmlTags() {
|
|
83
|
+
if (!searchPagePath) {
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
headTags: [
|
|
88
|
+
{
|
|
89
|
+
tagName: 'link',
|
|
90
|
+
attributes: {
|
|
91
|
+
rel: 'search',
|
|
92
|
+
type: 'application/opensearchdescription+xml',
|
|
93
|
+
title,
|
|
94
|
+
href: (0, utils_1.normalizeUrl)([baseUrl, OPEN_SEARCH_FILENAME]),
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
};
|
|
77
101
|
}
|
|
78
102
|
exports.default = themeSearchAlgolia;
|
|
79
|
-
var validateThemeConfig_1 = require(
|
|
80
|
-
Object.defineProperty(exports,
|
|
103
|
+
var validateThemeConfig_1 = require('./validateThemeConfig');
|
|
104
|
+
Object.defineProperty(exports, 'validateThemeConfig', {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
get: function () {
|
|
107
|
+
return validateThemeConfig_1.validateThemeConfig;
|
|
108
|
+
},
|
|
109
|
+
});
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
declare const _default: "\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\"\n xmlns:moz=\"http://www.mozilla.org/2006/browser/search/\">\n <ShortName><%= it.title %></ShortName>\n <Description>Search <%= it.title %></Description>\n <InputEncoding>UTF-8</InputEncoding>\n <% if (it.
|
|
7
|
+
declare const _default: "\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\"\n xmlns:moz=\"http://www.mozilla.org/2006/browser/search/\">\n <ShortName><%= it.title %></ShortName>\n <Description>Search <%= it.title %></Description>\n <InputEncoding>UTF-8</InputEncoding>\n <% if (it.faviconUrl) { _%>\n <Image width=\"16\" height=\"16\" type=\"image/x-icon\"><%= it.faviconUrl %></Image>\n <% } _%>\n <Url type=\"text/html\" method=\"get\" template=\"<%= it.searchUrl %>?q={searchTerms}\"/>\n <Url type=\"application/opensearchdescription+xml\" rel=\"self\" template=\"<%= it.siteUrl %>opensearch.xml\" />\n <moz:SearchForm><%= it.siteUrl %></moz:SearchForm>\n</OpenSearchDescription>\n";
|
|
8
8
|
export default _default;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
/**
|
|
3
3
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
4
|
*
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
-
Object.defineProperty(exports,
|
|
8
|
+
Object.defineProperty(exports, '__esModule', {value: true});
|
|
9
9
|
exports.default = `
|
|
10
10
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
11
11
|
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
|
|
@@ -13,11 +13,11 @@ exports.default = `
|
|
|
13
13
|
<ShortName><%= it.title %></ShortName>
|
|
14
14
|
<Description>Search <%= it.title %></Description>
|
|
15
15
|
<InputEncoding>UTF-8</InputEncoding>
|
|
16
|
-
<% if (it.
|
|
17
|
-
<Image width="16" height="16" type="image/x-icon"><%= it.
|
|
16
|
+
<% if (it.faviconUrl) { _%>
|
|
17
|
+
<Image width="16" height="16" type="image/x-icon"><%= it.faviconUrl %></Image>
|
|
18
18
|
<% } _%>
|
|
19
|
-
<Url type="text/html" method="get" template="<%= it.
|
|
20
|
-
<Url type="application/opensearchdescription+xml" rel="self" template="<%= it.
|
|
21
|
-
<moz:SearchForm><%= it.
|
|
19
|
+
<Url type="text/html" method="get" template="<%= it.searchUrl %>?q={searchTerms}"/>
|
|
20
|
+
<Url type="application/opensearchdescription+xml" rel="self" template="<%= it.siteUrl %>opensearch.xml" />
|
|
21
|
+
<moz:SearchForm><%= it.siteUrl %></moz:SearchForm>
|
|
22
22
|
</OpenSearchDescription>
|
|
23
23
|
`;
|
|
@@ -4,153 +4,209 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
import { createPortal } from 'react-dom';
|
|
7
|
+
import React, {useState, useRef, useCallback, useMemo} from 'react';
|
|
8
|
+
import {createPortal} from 'react-dom';
|
|
10
9
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import {useHistory} from '@docusaurus/router';
|
|
11
|
+
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
13
12
|
import Link from '@docusaurus/Link';
|
|
14
13
|
import Head from '@docusaurus/Head';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
14
|
+
import {isRegexpStringMatch, useSearchPage} from '@docusaurus/theme-common';
|
|
15
|
+
import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react';
|
|
16
|
+
import {useAlgoliaContextualFacetFilters} from '@docusaurus/theme-search-algolia/client';
|
|
17
|
+
import Translate, {translate} from '@docusaurus/Translate';
|
|
19
18
|
import styles from './styles.module.css';
|
|
20
19
|
let DocSearchModal = null;
|
|
21
|
-
function Hit({
|
|
22
|
-
|
|
20
|
+
function Hit({hit, children}) {
|
|
21
|
+
return <Link to={hit.url}>{children}</Link>;
|
|
23
22
|
}
|
|
24
|
-
function ResultsFooter({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
function ResultsFooter({state, onClose}) {
|
|
24
|
+
const {generateSearchPageLink} = useSearchPage();
|
|
25
|
+
return (
|
|
26
|
+
<Link to={generateSearchPageLink(state.query)} onClick={onClose}>
|
|
27
|
+
<Translate
|
|
28
|
+
id="theme.SearchBar.seeAll"
|
|
29
|
+
values={{count: state.context.nbHits}}>
|
|
30
|
+
{'See all {count} results'}
|
|
31
|
+
</Translate>
|
|
32
|
+
</Link>
|
|
33
|
+
);
|
|
29
34
|
}
|
|
30
35
|
function mergeFacetFilters(f1, f2) {
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
const normalize = (f) => (typeof f === 'string' ? [f] : f);
|
|
37
|
+
return [...normalize(f1), ...normalize(f2)];
|
|
33
38
|
}
|
|
34
|
-
function DocSearch({
|
|
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
|
-
searchContainer.current = document.createElement('div');
|
|
72
|
-
document.body.insertBefore(searchContainer.current, document.body.firstChild);
|
|
73
|
-
setIsOpen(true);
|
|
74
|
-
});
|
|
75
|
-
}, [importDocSearchModalIfNeeded, setIsOpen]);
|
|
76
|
-
const onClose = useCallback(() => {
|
|
77
|
-
var _a;
|
|
78
|
-
setIsOpen(false);
|
|
79
|
-
(_a = searchContainer.current) === null || _a === void 0 ? void 0 : _a.remove();
|
|
80
|
-
}, [setIsOpen]);
|
|
81
|
-
const onInput = useCallback((event) => {
|
|
82
|
-
importDocSearchModalIfNeeded().then(() => {
|
|
83
|
-
setIsOpen(true);
|
|
84
|
-
setInitialQuery(event.key);
|
|
85
|
-
});
|
|
86
|
-
}, [importDocSearchModalIfNeeded, setIsOpen, setInitialQuery]);
|
|
87
|
-
const navigator = useRef({
|
|
88
|
-
navigate({ itemUrl }) {
|
|
89
|
-
// Algolia results could contain URL's from other domains which cannot
|
|
90
|
-
// be served through history and should navigate with window.location
|
|
91
|
-
if (isRegexpStringMatch(externalUrlRegex, itemUrl)) {
|
|
92
|
-
window.location.href = itemUrl;
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
history.push(itemUrl);
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
}).current;
|
|
99
|
-
const transformItems = useRef((items) => items.map((item) => {
|
|
100
|
-
// If Algolia contains a external domain, we should navigate without relative URL
|
|
101
|
-
if (isRegexpStringMatch(externalUrlRegex, item.url)) {
|
|
102
|
-
return item;
|
|
103
|
-
}
|
|
104
|
-
// We transform the absolute URL into a relative URL.
|
|
105
|
-
const url = new URL(item.url);
|
|
106
|
-
return {
|
|
107
|
-
...item,
|
|
108
|
-
url: withBaseUrl(`${url.pathname}${url.hash}`),
|
|
109
|
-
};
|
|
110
|
-
})).current;
|
|
111
|
-
const resultsFooterComponent = useMemo(() =>
|
|
112
|
-
// eslint-disable-next-line react/no-unstable-nested-components
|
|
113
|
-
(footerProps) => <ResultsFooter {...footerProps} onClose={onClose}/>, [onClose]);
|
|
114
|
-
const transformSearchClient = useCallback((searchClient) => {
|
|
115
|
-
searchClient.addAlgoliaAgent('docusaurus', siteMetadata.docusaurusVersion);
|
|
116
|
-
return searchClient;
|
|
117
|
-
}, [siteMetadata.docusaurusVersion]);
|
|
118
|
-
useDocSearchKeyboardEvents({
|
|
119
|
-
isOpen,
|
|
120
|
-
onOpen,
|
|
121
|
-
onClose,
|
|
122
|
-
onInput,
|
|
123
|
-
searchButtonRef,
|
|
39
|
+
function DocSearch({contextualSearch, externalUrlRegex, ...props}) {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
const {siteMetadata} = useDocusaurusContext();
|
|
42
|
+
const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters();
|
|
43
|
+
const configFacetFilters =
|
|
44
|
+
(_b =
|
|
45
|
+
(_a = props.searchParameters) === null || _a === void 0
|
|
46
|
+
? void 0
|
|
47
|
+
: _a.facetFilters) !== null && _b !== void 0
|
|
48
|
+
? _b
|
|
49
|
+
: [];
|
|
50
|
+
const facetFilters = contextualSearch
|
|
51
|
+
? // Merge contextual search filters with config filters
|
|
52
|
+
mergeFacetFilters(contextualSearchFacetFilters, configFacetFilters)
|
|
53
|
+
: // ... or use config facetFilters
|
|
54
|
+
configFacetFilters;
|
|
55
|
+
// we let user override default searchParameters if he wants to
|
|
56
|
+
const searchParameters = {
|
|
57
|
+
...props.searchParameters,
|
|
58
|
+
facetFilters,
|
|
59
|
+
};
|
|
60
|
+
const {withBaseUrl} = useBaseUrlUtils();
|
|
61
|
+
const history = useHistory();
|
|
62
|
+
const searchContainer = useRef(null);
|
|
63
|
+
const searchButtonRef = useRef(null);
|
|
64
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
65
|
+
const [initialQuery, setInitialQuery] = useState(undefined);
|
|
66
|
+
const importDocSearchModalIfNeeded = useCallback(() => {
|
|
67
|
+
if (DocSearchModal) {
|
|
68
|
+
return Promise.resolve();
|
|
69
|
+
}
|
|
70
|
+
return Promise.all([
|
|
71
|
+
import('@docsearch/react/modal'),
|
|
72
|
+
import('@docsearch/react/style'),
|
|
73
|
+
import('./styles.css'),
|
|
74
|
+
]).then(([{DocSearchModal: Modal}]) => {
|
|
75
|
+
DocSearchModal = Modal;
|
|
124
76
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
77
|
+
}, []);
|
|
78
|
+
const onOpen = useCallback(() => {
|
|
79
|
+
importDocSearchModalIfNeeded().then(() => {
|
|
80
|
+
searchContainer.current = document.createElement('div');
|
|
81
|
+
document.body.insertBefore(
|
|
82
|
+
searchContainer.current,
|
|
83
|
+
document.body.firstChild,
|
|
84
|
+
);
|
|
85
|
+
setIsOpen(true);
|
|
129
86
|
});
|
|
130
|
-
|
|
87
|
+
}, [importDocSearchModalIfNeeded, setIsOpen]);
|
|
88
|
+
const onClose = useCallback(() => {
|
|
89
|
+
var _a;
|
|
90
|
+
setIsOpen(false);
|
|
91
|
+
(_a = searchContainer.current) === null || _a === void 0
|
|
92
|
+
? void 0
|
|
93
|
+
: _a.remove();
|
|
94
|
+
}, [setIsOpen]);
|
|
95
|
+
const onInput = useCallback(
|
|
96
|
+
(event) => {
|
|
97
|
+
importDocSearchModalIfNeeded().then(() => {
|
|
98
|
+
setIsOpen(true);
|
|
99
|
+
setInitialQuery(event.key);
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
[importDocSearchModalIfNeeded, setIsOpen, setInitialQuery],
|
|
103
|
+
);
|
|
104
|
+
const navigator = useRef({
|
|
105
|
+
navigate({itemUrl}) {
|
|
106
|
+
// Algolia results could contain URL's from other domains which cannot
|
|
107
|
+
// be served through history and should navigate with window.location
|
|
108
|
+
if (isRegexpStringMatch(externalUrlRegex, itemUrl)) {
|
|
109
|
+
window.location.href = itemUrl;
|
|
110
|
+
} else {
|
|
111
|
+
history.push(itemUrl);
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
}).current;
|
|
115
|
+
const transformItems = useRef((items) =>
|
|
116
|
+
items.map((item) => {
|
|
117
|
+
// If Algolia contains a external domain, we should navigate without
|
|
118
|
+
// relative URL
|
|
119
|
+
if (isRegexpStringMatch(externalUrlRegex, item.url)) {
|
|
120
|
+
return item;
|
|
121
|
+
}
|
|
122
|
+
// We transform the absolute URL into a relative URL.
|
|
123
|
+
const url = new URL(item.url);
|
|
124
|
+
return {
|
|
125
|
+
...item,
|
|
126
|
+
url: withBaseUrl(`${url.pathname}${url.hash}`),
|
|
127
|
+
};
|
|
128
|
+
}),
|
|
129
|
+
).current;
|
|
130
|
+
const resultsFooterComponent = useMemo(
|
|
131
|
+
() =>
|
|
132
|
+
// eslint-disable-next-line react/no-unstable-nested-components
|
|
133
|
+
(footerProps) =>
|
|
134
|
+
<ResultsFooter {...footerProps} onClose={onClose} />,
|
|
135
|
+
[onClose],
|
|
136
|
+
);
|
|
137
|
+
const transformSearchClient = useCallback(
|
|
138
|
+
(searchClient) => {
|
|
139
|
+
searchClient.addAlgoliaAgent(
|
|
140
|
+
'docusaurus',
|
|
141
|
+
siteMetadata.docusaurusVersion,
|
|
142
|
+
);
|
|
143
|
+
return searchClient;
|
|
144
|
+
},
|
|
145
|
+
[siteMetadata.docusaurusVersion],
|
|
146
|
+
);
|
|
147
|
+
useDocSearchKeyboardEvents({
|
|
148
|
+
isOpen,
|
|
149
|
+
onOpen,
|
|
150
|
+
onClose,
|
|
151
|
+
onInput,
|
|
152
|
+
searchButtonRef,
|
|
153
|
+
});
|
|
154
|
+
const translatedSearchLabel = translate({
|
|
155
|
+
id: 'theme.SearchBar.label',
|
|
156
|
+
message: 'Search',
|
|
157
|
+
description: 'The ARIA label and placeholder for search button',
|
|
158
|
+
});
|
|
159
|
+
return (
|
|
160
|
+
<>
|
|
131
161
|
<Head>
|
|
132
162
|
{/* This hints the browser that the website will load data from Algolia,
|
|
133
163
|
and allows it to preconnect to the DocSearch cluster. It makes the first
|
|
134
164
|
query faster, especially on mobile. */}
|
|
135
|
-
<link
|
|
165
|
+
<link
|
|
166
|
+
rel="preconnect"
|
|
167
|
+
href={`https://${props.appId}-dsn.algolia.net`}
|
|
168
|
+
crossOrigin="anonymous"
|
|
169
|
+
/>
|
|
136
170
|
</Head>
|
|
137
171
|
|
|
138
172
|
<div className={styles.searchBox}>
|
|
139
|
-
<DocSearchButton
|
|
173
|
+
<DocSearchButton
|
|
174
|
+
onTouchStart={importDocSearchModalIfNeeded}
|
|
175
|
+
onFocus={importDocSearchModalIfNeeded}
|
|
176
|
+
onMouseOver={importDocSearchModalIfNeeded}
|
|
177
|
+
onClick={onOpen}
|
|
178
|
+
ref={searchButtonRef}
|
|
179
|
+
translations={{
|
|
140
180
|
buttonText: translatedSearchLabel,
|
|
141
181
|
buttonAriaLabel: translatedSearchLabel,
|
|
142
|
-
|
|
182
|
+
}}
|
|
183
|
+
/>
|
|
143
184
|
</div>
|
|
144
185
|
|
|
145
186
|
{isOpen &&
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
187
|
+
DocSearchModal &&
|
|
188
|
+
searchContainer.current &&
|
|
189
|
+
createPortal(
|
|
190
|
+
<DocSearchModal
|
|
191
|
+
onClose={onClose}
|
|
192
|
+
initialScrollY={window.scrollY}
|
|
193
|
+
initialQuery={initialQuery}
|
|
194
|
+
navigator={navigator}
|
|
195
|
+
transformItems={transformItems}
|
|
196
|
+
hitComponent={Hit}
|
|
197
|
+
transformSearchClient={transformSearchClient}
|
|
198
|
+
{...(props.searchPagePath && {
|
|
199
|
+
resultsFooterComponent,
|
|
200
|
+
})}
|
|
201
|
+
{...props}
|
|
202
|
+
searchParameters={searchParameters}
|
|
203
|
+
/>,
|
|
204
|
+
searchContainer.current,
|
|
205
|
+
)}
|
|
206
|
+
</>
|
|
207
|
+
);
|
|
150
208
|
}
|
|
151
|
-
function SearchBar() {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return <DocSearch {...siteConfig.themeConfig.algolia}/>;
|
|
209
|
+
export default function SearchBar() {
|
|
210
|
+
const {siteConfig} = useDocusaurusContext();
|
|
211
|
+
return <DocSearch {...siteConfig.themeConfig.algolia} />;
|
|
155
212
|
}
|
|
156
|
-
export default SearchBar;
|