@docusaurus/theme-search-algolia 2.0.0-beta.13 → 2.0.0-beta.15
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/{theme/hooks/useSearchQuery.d.ts → client/index.d.ts} +1 -3
- package/lib/client/index.js +7 -0
- package/lib/client/useAlgoliaContextualFacetFilters.d.ts +7 -0
- package/lib/{theme/hooks → client}/useAlgoliaContextualFacetFilters.js +1 -1
- package/lib/index.d.ts +2 -4
- package/lib/index.js +7 -12
- package/lib/theme/SearchBar/index.js +10 -7
- package/lib/theme/SearchMetadata/index.d.ts +3 -2
- package/lib/theme/SearchMetadata/index.js +2 -2
- package/lib/theme/SearchPage/index.js +3 -4
- package/lib/theme/SearchPage/styles.module.css +4 -4
- package/lib/validateThemeConfig.d.ts +5 -0
- package/lib/validateThemeConfig.js +8 -7
- package/package.json +17 -10
- package/src/client/index.ts +8 -0
- package/src/{theme/hooks → client}/useAlgoliaContextualFacetFilters.ts +1 -2
- package/src/index.ts +8 -17
- package/src/theme/SearchBar/index.tsx +30 -15
- package/src/theme/SearchMetadata/index.tsx +3 -7
- package/src/theme/SearchPage/index.tsx +3 -3
- package/src/theme/SearchPage/styles.module.css +4 -4
- package/src/theme-search-algolia.d.ts +15 -26
- package/src/types.d.ts +4 -0
- package/src/validateThemeConfig.ts +4 -3
- package/copyUntypedFiles.js +0 -20
- package/lib/theme/hooks/useAlgoliaContextualFacetFilters.d.ts +0 -8
- package/lib/theme/hooks/useSearchQuery.js +0 -43
- package/src/__tests__/validateThemeConfig.test.js +0 -135
- package/src/theme/hooks/useSearchQuery.ts +0 -63
- package/tsconfig.browser.json +0 -8
- package/tsconfig.json +0 -9
- package/tsconfig.server.json +0 -4
|
@@ -4,6 +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
|
-
|
|
8
|
-
declare function useSearchQuery(): SearchQuery;
|
|
9
|
-
export default useSearchQuery;
|
|
7
|
+
export { useAlgoliaContextualFacetFilters } from './useAlgoliaContextualFacetFilters';
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export { useAlgoliaContextualFacetFilters } from './useAlgoliaContextualFacetFilters';
|
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export declare function useAlgoliaContextualFacetFilters(): [string, string[]];
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { useContextualSearchFilters } from '@docusaurus/theme-common';
|
|
8
8
|
// Translate search-engine agnostic search filters to Algolia search filters
|
|
9
|
-
export
|
|
9
|
+
export function useAlgoliaContextualFacetFilters() {
|
|
10
10
|
const { locale, tags } = useContextualSearchFilters();
|
|
11
11
|
// seems safe to convert locale->language, see AlgoliaSearchMetadata comment
|
|
12
12
|
const languageFilter = `language:${locale}`;
|
package/lib/index.d.ts
CHANGED
|
@@ -4,8 +4,6 @@
|
|
|
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 type {
|
|
8
|
-
export default function
|
|
9
|
-
baseUrl: string;
|
|
10
|
-
}): Plugin<void>;
|
|
7
|
+
import type { LoadContext, Plugin } from '@docusaurus/types';
|
|
8
|
+
export default function themeSearchAlgolia(context: LoadContext): Plugin<void>;
|
|
11
9
|
export { validateThemeConfig } from './validateThemeConfig';
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const fs_1 = (0, tslib_1.__importDefault)(require("fs"));
|
|
|
13
13
|
const eta_1 = require("eta");
|
|
14
14
|
const utils_1 = require("@docusaurus/utils");
|
|
15
15
|
const theme_translations_1 = require("@docusaurus/theme-translations");
|
|
16
|
+
const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
|
|
16
17
|
const opensearch_1 = (0, tslib_1.__importDefault)(require("./templates/opensearch"));
|
|
17
18
|
const lodash_1 = require("lodash");
|
|
18
19
|
const getCompiledOpenSearchTemplate = (0, lodash_1.memoize)(() => (0, eta_1.compile)(opensearch_1.default.trim()));
|
|
@@ -21,16 +22,10 @@ function renderOpenSearchTemplate(data) {
|
|
|
21
22
|
return compiled(data, eta_1.defaultConfig);
|
|
22
23
|
}
|
|
23
24
|
const OPEN_SEARCH_FILENAME = 'opensearch.xml';
|
|
24
|
-
function
|
|
25
|
+
function themeSearchAlgolia(context) {
|
|
25
26
|
const { baseUrl, siteConfig: { title, url, favicon }, i18n: { currentLocale }, } = context;
|
|
26
|
-
const pageComponent = './theme/SearchPage/index.js';
|
|
27
|
-
const pagePath = (0, utils_1.getSwizzledComponent)(pageComponent) ||
|
|
28
|
-
path_1.default.resolve(__dirname, pageComponent);
|
|
29
27
|
return {
|
|
30
28
|
name: 'docusaurus-theme-search-algolia',
|
|
31
|
-
getPathsToWatch() {
|
|
32
|
-
return [pagePath];
|
|
33
|
-
},
|
|
34
29
|
getThemePath() {
|
|
35
30
|
return path_1.default.resolve(__dirname, './theme');
|
|
36
31
|
},
|
|
@@ -46,7 +41,7 @@ function theme(context) {
|
|
|
46
41
|
async contentLoaded({ actions: { addRoute } }) {
|
|
47
42
|
addRoute({
|
|
48
43
|
path: (0, utils_1.normalizeUrl)([baseUrl, 'search']),
|
|
49
|
-
component:
|
|
44
|
+
component: '@theme/SearchPage',
|
|
50
45
|
exact: true,
|
|
51
46
|
});
|
|
52
47
|
},
|
|
@@ -58,9 +53,9 @@ function theme(context) {
|
|
|
58
53
|
favicon: favicon ? (0, utils_1.normalizeUrl)([url, baseUrl, favicon]) : null,
|
|
59
54
|
}));
|
|
60
55
|
}
|
|
61
|
-
catch (
|
|
62
|
-
|
|
63
|
-
throw
|
|
56
|
+
catch (e) {
|
|
57
|
+
logger_1.default.error('Generating OpenSearch file failed.');
|
|
58
|
+
throw e;
|
|
64
59
|
}
|
|
65
60
|
},
|
|
66
61
|
injectHtmlTags() {
|
|
@@ -80,6 +75,6 @@ function theme(context) {
|
|
|
80
75
|
},
|
|
81
76
|
};
|
|
82
77
|
}
|
|
83
|
-
exports.default =
|
|
78
|
+
exports.default = themeSearchAlgolia;
|
|
84
79
|
var validateThemeConfig_1 = require("./validateThemeConfig");
|
|
85
80
|
Object.defineProperty(exports, "validateThemeConfig", { enumerable: true, get: function () { return validateThemeConfig_1.validateThemeConfig; } });
|
|
@@ -12,10 +12,9 @@ import { useHistory } from '@docusaurus/router';
|
|
|
12
12
|
import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
|
|
13
13
|
import Link from '@docusaurus/Link';
|
|
14
14
|
import Head from '@docusaurus/Head';
|
|
15
|
-
import
|
|
16
|
-
import { isRegexpStringMatch } from '@docusaurus/theme-common';
|
|
15
|
+
import { isRegexpStringMatch, useSearchPage } from '@docusaurus/theme-common';
|
|
17
16
|
import { DocSearchButton, useDocSearchKeyboardEvents } from '@docsearch/react';
|
|
18
|
-
import useAlgoliaContextualFacetFilters from '@theme/
|
|
17
|
+
import { useAlgoliaContextualFacetFilters } from '@docusaurus/theme-search-algolia/client';
|
|
19
18
|
import { translate } from '@docusaurus/Translate';
|
|
20
19
|
import styles from './styles.module.css';
|
|
21
20
|
let DocSearchModal = null;
|
|
@@ -23,11 +22,15 @@ function Hit({ hit, children, }) {
|
|
|
23
22
|
return <Link to={hit.url}>{children}</Link>;
|
|
24
23
|
}
|
|
25
24
|
function ResultsFooter({ state, onClose }) {
|
|
26
|
-
const { generateSearchPageLink } =
|
|
25
|
+
const { generateSearchPageLink } = useSearchPage();
|
|
27
26
|
return (<Link to={generateSearchPageLink(state.query)} onClick={onClose}>
|
|
28
27
|
See all {state.context.nbHits} results
|
|
29
28
|
</Link>);
|
|
30
29
|
}
|
|
30
|
+
function mergeFacetFilters(f1, f2) {
|
|
31
|
+
const normalize = (f) => f instanceof Array ? f : [f];
|
|
32
|
+
return [...normalize(f1), ...normalize(f2)];
|
|
33
|
+
}
|
|
31
34
|
function DocSearch({ contextualSearch, externalUrlRegex, ...props }) {
|
|
32
35
|
var _a, _b;
|
|
33
36
|
const { siteMetadata } = useDocusaurusContext();
|
|
@@ -35,7 +38,7 @@ function DocSearch({ contextualSearch, externalUrlRegex, ...props }) {
|
|
|
35
38
|
const configFacetFilters = (_b = (_a = props.searchParameters) === null || _a === void 0 ? void 0 : _a.facetFilters) !== null && _b !== void 0 ? _b : [];
|
|
36
39
|
const facetFilters = contextualSearch
|
|
37
40
|
? // Merge contextual search filters with config filters
|
|
38
|
-
|
|
41
|
+
mergeFacetFilters(contextualSearchFacetFilters, configFacetFilters)
|
|
39
42
|
: // ... or use config facetFilters
|
|
40
43
|
configFacetFilters;
|
|
41
44
|
// we let user override default searchParameters if he wants to
|
|
@@ -105,9 +108,9 @@ function DocSearch({ contextualSearch, externalUrlRegex, ...props }) {
|
|
|
105
108
|
url: withBaseUrl(`${url.pathname}${url.hash}`),
|
|
106
109
|
};
|
|
107
110
|
})).current;
|
|
108
|
-
const resultsFooterComponent = useMemo(
|
|
111
|
+
const resultsFooterComponent = useMemo(() =>
|
|
109
112
|
// eslint-disable-next-line react/no-unstable-nested-components
|
|
110
|
-
(
|
|
113
|
+
(footerProps) => <ResultsFooter {...footerProps} onClose={onClose}/>, [onClose]);
|
|
111
114
|
const transformSearchClient = useCallback((searchClient) => {
|
|
112
115
|
searchClient.addAlgoliaAgent('docusaurus', siteMetadata.docusaurusVersion);
|
|
113
116
|
return searchClient;
|
|
@@ -4,7 +4,8 @@
|
|
|
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
|
+
/// <reference types="@docusaurus/theme-classic" />
|
|
7
8
|
/// <reference types="react" />
|
|
8
|
-
import type {
|
|
9
|
-
declare function SearchMetadata({ locale, version, tag
|
|
9
|
+
import type { Props } from '@theme/SearchMetadata';
|
|
10
|
+
declare function SearchMetadata({ locale, version, tag }: Props): JSX.Element;
|
|
10
11
|
export default SearchMetadata;
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import Head from '@docusaurus/Head';
|
|
9
|
-
// Override default/agnostic
|
|
10
|
-
function SearchMetadata({ locale, version, tag
|
|
9
|
+
// Override default/agnostic SearchMetadata to use Algolia-specific metadata
|
|
10
|
+
function SearchMetadata({ locale, version, tag }) {
|
|
11
11
|
// Seems safe to consider here the locale is the language,
|
|
12
12
|
// as the existing docsearch:language filter is afaik a regular string-based filter
|
|
13
13
|
const language = locale;
|
|
@@ -13,10 +13,9 @@ import clsx from 'clsx';
|
|
|
13
13
|
import Head from '@docusaurus/Head';
|
|
14
14
|
import Link from '@docusaurus/Link';
|
|
15
15
|
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
16
|
-
import { useTitleFormatter, usePluralForm, isRegexpStringMatch, useDynamicCallback, } from '@docusaurus/theme-common';
|
|
16
|
+
import { useTitleFormatter, usePluralForm, isRegexpStringMatch, useDynamicCallback, useSearchPage, } from '@docusaurus/theme-common';
|
|
17
17
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
18
|
-
import { useAllDocsData } from '@
|
|
19
|
-
import useSearchQuery from '@theme/hooks/useSearchQuery';
|
|
18
|
+
import { useAllDocsData } from '@docusaurus/plugin-content-docs/client';
|
|
20
19
|
import Layout from '@theme/Layout';
|
|
21
20
|
import Translate, { translate } from '@docusaurus/Translate';
|
|
22
21
|
import styles from './styles.module.css';
|
|
@@ -67,7 +66,7 @@ function SearchPage() {
|
|
|
67
66
|
algolia: { appId, apiKey, indexName, externalUrlRegex }, }, }, i18n: { currentLocale }, } = useDocusaurusContext();
|
|
68
67
|
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
69
68
|
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
70
|
-
const { searchQuery, setSearchQuery } =
|
|
69
|
+
const { searchQuery, setSearchQuery } = useSearchPage();
|
|
71
70
|
const initialSearchResultState = {
|
|
72
71
|
items: [],
|
|
73
72
|
query: null,
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
.searchResultItemSummary {
|
|
61
|
-
margin: 0.5rem 0 0
|
|
61
|
+
margin: 0.5rem 0 0;
|
|
62
62
|
font-style: italic;
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
border: 0.4em solid #eee;
|
|
99
99
|
border-top-color: var(--ifm-color-primary);
|
|
100
100
|
border-radius: 50%;
|
|
101
|
-
animation:
|
|
101
|
+
animation: loading-spin 1s linear infinite;
|
|
102
102
|
margin: 0 auto;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
@keyframes
|
|
105
|
+
@keyframes loading-spin {
|
|
106
106
|
100% {
|
|
107
107
|
transform: rotate(360deg);
|
|
108
108
|
}
|
|
@@ -114,6 +114,6 @@
|
|
|
114
114
|
|
|
115
115
|
:global(.search-result-match) {
|
|
116
116
|
color: var(--docsearch-hit-color);
|
|
117
|
-
background:
|
|
117
|
+
background: rgb(255 215 142 / 25%);
|
|
118
118
|
padding: 0.09em 0;
|
|
119
119
|
}
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { Joi } from '@docusaurus/utils-validation';
|
|
8
8
|
import type { ThemeConfig, Validate, ValidationResult } from '@docusaurus/types';
|
|
9
|
+
export declare const DEFAULT_CONFIG: {
|
|
10
|
+
contextualSearch: boolean;
|
|
11
|
+
appId: string;
|
|
12
|
+
searchParameters: {};
|
|
13
|
+
};
|
|
9
14
|
export declare const Schema: Joi.ObjectSchema<any>;
|
|
10
15
|
export declare function validateThemeConfig({ validate, themeConfig, }: {
|
|
11
16
|
validate: Validate<ThemeConfig>;
|
|
@@ -6,27 +6,28 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.validateThemeConfig = exports.Schema = void 0;
|
|
9
|
+
exports.validateThemeConfig = exports.Schema = exports.DEFAULT_CONFIG = void 0;
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
exports.DEFAULT_CONFIG = {
|
|
12
|
+
// enabled by default, as it makes sense in most cases
|
|
13
|
+
// see also https://github.com/facebook/docusaurus/issues/5880
|
|
14
|
+
contextualSearch: true,
|
|
13
15
|
// By default, all Docusaurus sites are using the same AppId
|
|
14
16
|
// This has been designed on purpose with Algolia.
|
|
15
17
|
appId: 'BH4D9OD16A',
|
|
16
18
|
searchParameters: {},
|
|
17
19
|
};
|
|
18
|
-
exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
|
|
19
20
|
exports.Schema = utils_validation_1.Joi.object({
|
|
20
21
|
algolia: utils_validation_1.Joi.object({
|
|
21
22
|
// Docusaurus attributes
|
|
22
|
-
contextualSearch: utils_validation_1.Joi.boolean().default(DEFAULT_CONFIG.contextualSearch),
|
|
23
|
+
contextualSearch: utils_validation_1.Joi.boolean().default(exports.DEFAULT_CONFIG.contextualSearch),
|
|
23
24
|
externalUrlRegex: utils_validation_1.Joi.string().optional(),
|
|
24
25
|
// Algolia attributes
|
|
25
|
-
appId: utils_validation_1.Joi.string().default(DEFAULT_CONFIG.appId),
|
|
26
|
+
appId: utils_validation_1.Joi.string().default(exports.DEFAULT_CONFIG.appId),
|
|
26
27
|
apiKey: utils_validation_1.Joi.string().required(),
|
|
27
28
|
indexName: utils_validation_1.Joi.string().required(),
|
|
28
29
|
searchParameters: utils_validation_1.Joi.object()
|
|
29
|
-
.default(DEFAULT_CONFIG.searchParameters)
|
|
30
|
+
.default(exports.DEFAULT_CONFIG.searchParameters)
|
|
30
31
|
.unknown(),
|
|
31
32
|
})
|
|
32
33
|
.label('themeConfig.algolia')
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/theme-search-algolia",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.15",
|
|
4
4
|
"description": "Algolia search component for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
"./client": "./lib/client/index.js",
|
|
8
|
+
".": "./lib/index.js"
|
|
9
|
+
},
|
|
6
10
|
"types": "src/theme-search-algolia.d.ts",
|
|
7
11
|
"publishConfig": {
|
|
8
12
|
"access": "public"
|
|
@@ -17,23 +21,26 @@
|
|
|
17
21
|
"build": "yarn build:server && yarn build:browser && yarn build:copy",
|
|
18
22
|
"build:server": "tsc --project tsconfig.server.json",
|
|
19
23
|
"build:browser": "tsc --project tsconfig.browser.json",
|
|
20
|
-
"build:copy": "node copyUntypedFiles.
|
|
24
|
+
"build:copy": "node copyUntypedFiles.mjs"
|
|
21
25
|
},
|
|
22
26
|
"dependencies": {
|
|
23
27
|
"@docsearch/react": "^3.0.0-alpha.39",
|
|
24
|
-
"@docusaurus/core": "2.0.0-beta.
|
|
25
|
-
"@docusaurus/
|
|
26
|
-
"@docusaurus/theme-
|
|
27
|
-
"@docusaurus/
|
|
28
|
-
"@docusaurus/utils
|
|
28
|
+
"@docusaurus/core": "2.0.0-beta.15",
|
|
29
|
+
"@docusaurus/logger": "2.0.0-beta.15",
|
|
30
|
+
"@docusaurus/theme-common": "2.0.0-beta.15",
|
|
31
|
+
"@docusaurus/theme-translations": "2.0.0-beta.15",
|
|
32
|
+
"@docusaurus/utils": "2.0.0-beta.15",
|
|
33
|
+
"@docusaurus/utils-validation": "2.0.0-beta.15",
|
|
29
34
|
"algoliasearch": "^4.10.5",
|
|
30
35
|
"algoliasearch-helper": "^3.5.5",
|
|
31
36
|
"clsx": "^1.1.1",
|
|
32
37
|
"eta": "^1.12.3",
|
|
33
|
-
"lodash": "^4.17.20"
|
|
38
|
+
"lodash": "^4.17.20",
|
|
39
|
+
"tslib": "^2.3.1",
|
|
40
|
+
"utility-types": "^3.10.0"
|
|
34
41
|
},
|
|
35
42
|
"devDependencies": {
|
|
36
|
-
"@docusaurus/module-type-aliases": "2.0.0-beta.
|
|
43
|
+
"@docusaurus/module-type-aliases": "2.0.0-beta.15",
|
|
37
44
|
"fs-extra": "^10.0.0"
|
|
38
45
|
},
|
|
39
46
|
"peerDependencies": {
|
|
@@ -43,5 +50,5 @@
|
|
|
43
50
|
"engines": {
|
|
44
51
|
"node": ">=14"
|
|
45
52
|
},
|
|
46
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "6cfad16436c07d8d11e5c2e1486dc59afd483e33"
|
|
47
54
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
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
|
+
export {useAlgoliaContextualFacetFilters} from './useAlgoliaContextualFacetFilters';
|
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {useAlgoliaContextualFacetFiltersReturns} from '@theme/hooks/useAlgoliaContextualFacetFilters';
|
|
9
8
|
import {useContextualSearchFilters} from '@docusaurus/theme-common';
|
|
10
9
|
|
|
11
10
|
// Translate search-engine agnostic search filters to Algolia search filters
|
|
12
|
-
export
|
|
11
|
+
export function useAlgoliaContextualFacetFilters(): [string, string[]] {
|
|
13
12
|
const {locale, tags} = useContextualSearchFilters();
|
|
14
13
|
|
|
15
14
|
// seems safe to convert locale->language, see AlgoliaSearchMetadata comment
|
package/src/index.ts
CHANGED
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs';
|
|
10
10
|
import {defaultConfig, compile} from 'eta';
|
|
11
|
-
import {normalizeUrl
|
|
11
|
+
import {normalizeUrl} from '@docusaurus/utils';
|
|
12
12
|
import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations';
|
|
13
|
+
import logger from '@docusaurus/logger';
|
|
13
14
|
import openSearchTemplate from './templates/opensearch';
|
|
14
15
|
import {memoize} from 'lodash';
|
|
15
16
|
|
|
16
|
-
import type {
|
|
17
|
+
import type {LoadContext, Plugin} from '@docusaurus/types';
|
|
17
18
|
|
|
18
19
|
const getCompiledOpenSearchTemplate = memoize(() =>
|
|
19
20
|
compile(openSearchTemplate.trim()),
|
|
@@ -30,26 +31,16 @@ function renderOpenSearchTemplate(data: {
|
|
|
30
31
|
|
|
31
32
|
const OPEN_SEARCH_FILENAME = 'opensearch.xml';
|
|
32
33
|
|
|
33
|
-
export default function
|
|
34
|
-
context: DocusaurusContext & {baseUrl: string},
|
|
35
|
-
): Plugin<void> {
|
|
34
|
+
export default function themeSearchAlgolia(context: LoadContext): Plugin<void> {
|
|
36
35
|
const {
|
|
37
36
|
baseUrl,
|
|
38
37
|
siteConfig: {title, url, favicon},
|
|
39
38
|
i18n: {currentLocale},
|
|
40
39
|
} = context;
|
|
41
|
-
const pageComponent = './theme/SearchPage/index.js';
|
|
42
|
-
const pagePath =
|
|
43
|
-
getSwizzledComponent(pageComponent) ||
|
|
44
|
-
path.resolve(__dirname, pageComponent);
|
|
45
40
|
|
|
46
41
|
return {
|
|
47
42
|
name: 'docusaurus-theme-search-algolia',
|
|
48
43
|
|
|
49
|
-
getPathsToWatch() {
|
|
50
|
-
return [pagePath];
|
|
51
|
-
},
|
|
52
|
-
|
|
53
44
|
getThemePath() {
|
|
54
45
|
return path.resolve(__dirname, './theme');
|
|
55
46
|
},
|
|
@@ -68,7 +59,7 @@ export default function theme(
|
|
|
68
59
|
async contentLoaded({actions: {addRoute}}) {
|
|
69
60
|
addRoute({
|
|
70
61
|
path: normalizeUrl([baseUrl, 'search']),
|
|
71
|
-
component:
|
|
62
|
+
component: '@theme/SearchPage',
|
|
72
63
|
exact: true,
|
|
73
64
|
});
|
|
74
65
|
},
|
|
@@ -83,9 +74,9 @@ export default function theme(
|
|
|
83
74
|
favicon: favicon ? normalizeUrl([url, baseUrl, favicon]) : null,
|
|
84
75
|
}),
|
|
85
76
|
);
|
|
86
|
-
} catch (
|
|
87
|
-
|
|
88
|
-
throw
|
|
77
|
+
} catch (e) {
|
|
78
|
+
logger.error('Generating OpenSearch file failed.');
|
|
79
|
+
throw e;
|
|
89
80
|
}
|
|
90
81
|
},
|
|
91
82
|
|
|
@@ -13,10 +13,9 @@ import {useHistory} from '@docusaurus/router';
|
|
|
13
13
|
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
14
14
|
import Link from '@docusaurus/Link';
|
|
15
15
|
import Head from '@docusaurus/Head';
|
|
16
|
-
import
|
|
17
|
-
import {isRegexpStringMatch} from '@docusaurus/theme-common';
|
|
16
|
+
import {isRegexpStringMatch, useSearchPage} from '@docusaurus/theme-common';
|
|
18
17
|
import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react';
|
|
19
|
-
import useAlgoliaContextualFacetFilters from '@theme/
|
|
18
|
+
import {useAlgoliaContextualFacetFilters} from '@docusaurus/theme-search-algolia/client';
|
|
20
19
|
import {translate} from '@docusaurus/Translate';
|
|
21
20
|
import styles from './styles.module.css';
|
|
22
21
|
|
|
@@ -56,7 +55,7 @@ type ResultsFooterProps = {
|
|
|
56
55
|
};
|
|
57
56
|
|
|
58
57
|
function ResultsFooter({state, onClose}: ResultsFooterProps) {
|
|
59
|
-
const {generateSearchPageLink} =
|
|
58
|
+
const {generateSearchPageLink} = useSearchPage();
|
|
60
59
|
|
|
61
60
|
return (
|
|
62
61
|
<Link to={generateSearchPageLink(state.query)} onClick={onClose}>
|
|
@@ -65,6 +64,18 @@ function ResultsFooter({state, onClose}: ResultsFooterProps) {
|
|
|
65
64
|
);
|
|
66
65
|
}
|
|
67
66
|
|
|
67
|
+
type FacetFilters = Required<
|
|
68
|
+
Required<DocSearchProps>['searchParameters']
|
|
69
|
+
>['facetFilters'];
|
|
70
|
+
|
|
71
|
+
function mergeFacetFilters(f1: FacetFilters, f2: FacetFilters): FacetFilters {
|
|
72
|
+
const normalize = (
|
|
73
|
+
f: FacetFilters,
|
|
74
|
+
): readonly string[] | ReadonlyArray<readonly string[]> =>
|
|
75
|
+
f instanceof Array ? f : [f];
|
|
76
|
+
return [...normalize(f1), ...normalize(f2)] as FacetFilters;
|
|
77
|
+
}
|
|
78
|
+
|
|
68
79
|
function DocSearch({
|
|
69
80
|
contextualSearch,
|
|
70
81
|
externalUrlRegex,
|
|
@@ -72,18 +83,20 @@ function DocSearch({
|
|
|
72
83
|
}: DocSearchProps) {
|
|
73
84
|
const {siteMetadata} = useDocusaurusContext();
|
|
74
85
|
|
|
75
|
-
const contextualSearchFacetFilters =
|
|
86
|
+
const contextualSearchFacetFilters =
|
|
87
|
+
useAlgoliaContextualFacetFilters() as FacetFilters;
|
|
76
88
|
|
|
77
|
-
const configFacetFilters =
|
|
89
|
+
const configFacetFilters: FacetFilters =
|
|
90
|
+
props.searchParameters?.facetFilters ?? [];
|
|
78
91
|
|
|
79
|
-
const facetFilters = contextualSearch
|
|
92
|
+
const facetFilters: FacetFilters = contextualSearch
|
|
80
93
|
? // Merge contextual search filters with config filters
|
|
81
|
-
|
|
94
|
+
mergeFacetFilters(contextualSearchFacetFilters, configFacetFilters)
|
|
82
95
|
: // ... or use config facetFilters
|
|
83
96
|
configFacetFilters;
|
|
84
97
|
|
|
85
98
|
// we let user override default searchParameters if he wants to
|
|
86
|
-
const searchParameters = {
|
|
99
|
+
const searchParameters: DocSearchProps['searchParameters'] = {
|
|
87
100
|
...props.searchParameters,
|
|
88
101
|
facetFilters,
|
|
89
102
|
};
|
|
@@ -168,12 +181,14 @@ function DocSearch({
|
|
|
168
181
|
}),
|
|
169
182
|
).current;
|
|
170
183
|
|
|
171
|
-
const resultsFooterComponent =
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
const resultsFooterComponent: DocSearchProps['resultsFooterComponent'] =
|
|
185
|
+
useMemo(
|
|
186
|
+
() =>
|
|
187
|
+
// eslint-disable-next-line react/no-unstable-nested-components
|
|
188
|
+
(footerProps: Omit<ResultsFooterProps, 'onClose'>): JSX.Element =>
|
|
189
|
+
<ResultsFooter {...footerProps} onClose={onClose} />,
|
|
190
|
+
[onClose],
|
|
191
|
+
);
|
|
177
192
|
|
|
178
193
|
const transformSearchClient = useCallback(
|
|
179
194
|
(searchClient) => {
|
|
@@ -8,14 +8,10 @@
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
|
|
10
10
|
import Head from '@docusaurus/Head';
|
|
11
|
-
import type {
|
|
11
|
+
import type {Props} from '@theme/SearchMetadata';
|
|
12
12
|
|
|
13
|
-
// Override default/agnostic
|
|
14
|
-
function SearchMetadata({
|
|
15
|
-
locale,
|
|
16
|
-
version,
|
|
17
|
-
tag,
|
|
18
|
-
}: SearchMetadataProps): JSX.Element {
|
|
13
|
+
// Override default/agnostic SearchMetadata to use Algolia-specific metadata
|
|
14
|
+
function SearchMetadata({locale, version, tag}: Props): JSX.Element {
|
|
19
15
|
// Seems safe to consider here the locale is the language,
|
|
20
16
|
// as the existing docsearch:language filter is afaik a regular string-based filter
|
|
21
17
|
const language = locale;
|
|
@@ -22,10 +22,10 @@ import {
|
|
|
22
22
|
usePluralForm,
|
|
23
23
|
isRegexpStringMatch,
|
|
24
24
|
useDynamicCallback,
|
|
25
|
+
useSearchPage,
|
|
25
26
|
} from '@docusaurus/theme-common';
|
|
26
27
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
27
|
-
import {useAllDocsData} from '@
|
|
28
|
-
import useSearchQuery from '@theme/hooks/useSearchQuery';
|
|
28
|
+
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
29
29
|
import Layout from '@theme/Layout';
|
|
30
30
|
import Translate, {translate} from '@docusaurus/Translate';
|
|
31
31
|
import styles from './styles.module.css';
|
|
@@ -162,7 +162,7 @@ function SearchPage(): JSX.Element {
|
|
|
162
162
|
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
163
163
|
|
|
164
164
|
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
165
|
-
const {searchQuery, setSearchQuery} =
|
|
165
|
+
const {searchQuery, setSearchQuery} = useSearchPage();
|
|
166
166
|
const initialSearchResultState: ResultDispatcherState = {
|
|
167
167
|
items: [],
|
|
168
168
|
query: null,
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
.searchResultItemSummary {
|
|
61
|
-
margin: 0.5rem 0 0
|
|
61
|
+
margin: 0.5rem 0 0;
|
|
62
62
|
font-style: italic;
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -98,11 +98,11 @@
|
|
|
98
98
|
border: 0.4em solid #eee;
|
|
99
99
|
border-top-color: var(--ifm-color-primary);
|
|
100
100
|
border-radius: 50%;
|
|
101
|
-
animation:
|
|
101
|
+
animation: loading-spin 1s linear infinite;
|
|
102
102
|
margin: 0 auto;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
@keyframes
|
|
105
|
+
@keyframes loading-spin {
|
|
106
106
|
100% {
|
|
107
107
|
transform: rotate(360deg);
|
|
108
108
|
}
|
|
@@ -114,6 +114,6 @@
|
|
|
114
114
|
|
|
115
115
|
:global(.search-result-match) {
|
|
116
116
|
color: var(--docsearch-hit-color);
|
|
117
|
-
background:
|
|
117
|
+
background: rgb(255 215 142 / 25%);
|
|
118
118
|
padding: 0.09em 0;
|
|
119
119
|
}
|
|
@@ -6,23 +6,23 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
declare module '@docusaurus/theme-search-algolia' {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export type UserThemeConfig = DeepPartial<ThemeConfig>;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
|
-
declare module '@theme/
|
|
23
|
-
export
|
|
24
|
-
|
|
25
|
-
export default function useAlgoliaContextualFacetFilters(): useAlgoliaContextualFacetFiltersReturns;
|
|
24
|
+
declare module '@docusaurus/theme-search-algolia/client' {
|
|
25
|
+
export function useAlgoliaContextualFacetFilters(): [string, string[]];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
declare module '@theme/SearchPage' {
|
|
@@ -30,17 +30,6 @@ declare module '@theme/SearchPage' {
|
|
|
30
30
|
export default SearchPage;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
declare module '@theme/SearchMetadata' {
|
|
34
|
-
export type SearchMetadataProps = {
|
|
35
|
-
readonly locale?: string;
|
|
36
|
-
readonly version?: string;
|
|
37
|
-
readonly tag?: string;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const SearchMetadata: (props: SearchMetadataProps) => JSX.Element;
|
|
41
|
-
export default SearchMetadata;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
33
|
declare module '@theme/SearchBar' {
|
|
45
34
|
const SearchBar: () => JSX.Element;
|
|
46
35
|
export default SearchBar;
|
package/src/types.d.ts
CHANGED
|
@@ -8,3 +8,7 @@
|
|
|
8
8
|
/// <reference types="@docusaurus/module-type-aliases" />
|
|
9
9
|
/// <reference types="@docusaurus/theme-common" />
|
|
10
10
|
/// <reference types="@docusaurus/theme-classic" />
|
|
11
|
+
|
|
12
|
+
export type FacetFilters = Required<
|
|
13
|
+
Required<DocSearchProps>['searchParameters']
|
|
14
|
+
>['facetFilters'];
|
|
@@ -8,8 +8,10 @@
|
|
|
8
8
|
import {Joi} from '@docusaurus/utils-validation';
|
|
9
9
|
import type {ThemeConfig, Validate, ValidationResult} from '@docusaurus/types';
|
|
10
10
|
|
|
11
|
-
const DEFAULT_CONFIG = {
|
|
12
|
-
|
|
11
|
+
export const DEFAULT_CONFIG = {
|
|
12
|
+
// enabled by default, as it makes sense in most cases
|
|
13
|
+
// see also https://github.com/facebook/docusaurus/issues/5880
|
|
14
|
+
contextualSearch: true,
|
|
13
15
|
|
|
14
16
|
// By default, all Docusaurus sites are using the same AppId
|
|
15
17
|
// This has been designed on purpose with Algolia.
|
|
@@ -17,7 +19,6 @@ const DEFAULT_CONFIG = {
|
|
|
17
19
|
|
|
18
20
|
searchParameters: {},
|
|
19
21
|
};
|
|
20
|
-
exports.DEFAULT_CONFIG = DEFAULT_CONFIG;
|
|
21
22
|
|
|
22
23
|
export const Schema = Joi.object({
|
|
23
24
|
algolia: Joi.object({
|
package/copyUntypedFiles.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
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
|
-
const path = require('path');
|
|
9
|
-
const fs = require('fs-extra');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Copy all untyped and static assets files to lib.
|
|
13
|
-
*/
|
|
14
|
-
const srcDir = path.resolve(__dirname, 'src');
|
|
15
|
-
const libDir = path.resolve(__dirname, 'lib');
|
|
16
|
-
fs.copySync(srcDir, libDir, {
|
|
17
|
-
filter(filepath) {
|
|
18
|
-
return !/__tests__/.test(filepath) && !/\.tsx?$/.test(filepath);
|
|
19
|
-
},
|
|
20
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
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
|
-
import type { useAlgoliaContextualFacetFiltersReturns } from '@theme/hooks/useAlgoliaContextualFacetFilters';
|
|
8
|
-
export default function useAlgoliaContextualFacetFilters(): useAlgoliaContextualFacetFiltersReturns;
|
|
@@ -1,43 +0,0 @@
|
|
|
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
|
-
import { useHistory } from '@docusaurus/router';
|
|
8
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
9
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
10
|
-
const SEARCH_PARAM_QUERY = 'q';
|
|
11
|
-
function useSearchQuery() {
|
|
12
|
-
const history = useHistory();
|
|
13
|
-
const { siteConfig: { baseUrl }, } = useDocusaurusContext();
|
|
14
|
-
const [searchQuery, setSearchQueryState] = useState('');
|
|
15
|
-
// Init search query just after React hydration
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
var _a;
|
|
18
|
-
const searchQueryStringValue = (_a = new URLSearchParams(window.location.search).get(SEARCH_PARAM_QUERY)) !== null && _a !== void 0 ? _a : '';
|
|
19
|
-
setSearchQueryState(searchQueryStringValue);
|
|
20
|
-
}, []);
|
|
21
|
-
const setSearchQuery = useCallback((newSearchQuery) => {
|
|
22
|
-
const searchParams = new URLSearchParams(window.location.search);
|
|
23
|
-
if (newSearchQuery) {
|
|
24
|
-
searchParams.set(SEARCH_PARAM_QUERY, newSearchQuery);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
searchParams.delete(SEARCH_PARAM_QUERY);
|
|
28
|
-
}
|
|
29
|
-
history.replace({
|
|
30
|
-
search: searchParams.toString(),
|
|
31
|
-
});
|
|
32
|
-
setSearchQueryState(newSearchQuery);
|
|
33
|
-
}, [history]);
|
|
34
|
-
const generateSearchPageLink = useCallback((targetSearchQuery) =>
|
|
35
|
-
// Refer to https://github.com/facebook/docusaurus/pull/2838
|
|
36
|
-
`${baseUrl}search?q=${encodeURIComponent(targetSearchQuery)}`, [baseUrl]);
|
|
37
|
-
return {
|
|
38
|
-
searchQuery,
|
|
39
|
-
setSearchQuery,
|
|
40
|
-
generateSearchPageLink,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
export default useSearchQuery;
|
|
@@ -1,135 +0,0 @@
|
|
|
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
|
-
const {validateThemeConfig, DEFAULT_CONFIG} = require('../validateThemeConfig');
|
|
9
|
-
|
|
10
|
-
function testValidateThemeConfig(themeConfig) {
|
|
11
|
-
function validate(schema, cfg) {
|
|
12
|
-
const {value, error} = schema.validate(cfg, {
|
|
13
|
-
convert: false,
|
|
14
|
-
});
|
|
15
|
-
if (error) {
|
|
16
|
-
throw error;
|
|
17
|
-
}
|
|
18
|
-
return value;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return validateThemeConfig({themeConfig, validate});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('validateThemeConfig', () => {
|
|
25
|
-
test('minimal config', () => {
|
|
26
|
-
const algolia = {
|
|
27
|
-
indexName: 'index',
|
|
28
|
-
apiKey: 'apiKey',
|
|
29
|
-
};
|
|
30
|
-
expect(testValidateThemeConfig({algolia})).toEqual({
|
|
31
|
-
algolia: {
|
|
32
|
-
...DEFAULT_CONFIG,
|
|
33
|
-
...algolia,
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test('unknown attributes', () => {
|
|
39
|
-
const algolia = {
|
|
40
|
-
indexName: 'index',
|
|
41
|
-
apiKey: 'apiKey',
|
|
42
|
-
unknownKey: 'unknownKey',
|
|
43
|
-
};
|
|
44
|
-
expect(testValidateThemeConfig({algolia})).toEqual({
|
|
45
|
-
algolia: {
|
|
46
|
-
...DEFAULT_CONFIG,
|
|
47
|
-
...algolia,
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test('undefined config', () => {
|
|
53
|
-
const algolia = undefined;
|
|
54
|
-
expect(() =>
|
|
55
|
-
testValidateThemeConfig({algolia}),
|
|
56
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
57
|
-
`"\\"themeConfig.algolia\\" is required"`,
|
|
58
|
-
);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test('undefined config 2', () => {
|
|
62
|
-
expect(() =>
|
|
63
|
-
testValidateThemeConfig({}),
|
|
64
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
65
|
-
`"\\"themeConfig.algolia\\" is required"`,
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('empty config', () => {
|
|
70
|
-
const algolia = {};
|
|
71
|
-
expect(() =>
|
|
72
|
-
testValidateThemeConfig({algolia}),
|
|
73
|
-
).toThrowErrorMatchingInlineSnapshot(`"\\"algolia.apiKey\\" is required"`);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('missing indexName config', () => {
|
|
77
|
-
const algolia = {apiKey: 'apiKey'};
|
|
78
|
-
expect(() =>
|
|
79
|
-
testValidateThemeConfig({algolia}),
|
|
80
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
81
|
-
`"\\"algolia.indexName\\" is required"`,
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('missing apiKey config', () => {
|
|
86
|
-
const algolia = {indexName: 'indexName'};
|
|
87
|
-
expect(() =>
|
|
88
|
-
testValidateThemeConfig({algolia}),
|
|
89
|
-
).toThrowErrorMatchingInlineSnapshot(`"\\"algolia.apiKey\\" is required"`);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test('contextualSearch config', () => {
|
|
93
|
-
const algolia = {
|
|
94
|
-
indexName: 'index',
|
|
95
|
-
apiKey: 'apiKey',
|
|
96
|
-
contextualSearch: true,
|
|
97
|
-
};
|
|
98
|
-
expect(testValidateThemeConfig({algolia})).toEqual({
|
|
99
|
-
algolia: {
|
|
100
|
-
...DEFAULT_CONFIG,
|
|
101
|
-
...algolia,
|
|
102
|
-
},
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('externalUrlRegex config', () => {
|
|
107
|
-
const algolia = {
|
|
108
|
-
indexName: 'index',
|
|
109
|
-
apiKey: 'apiKey',
|
|
110
|
-
externalUrlRegex: 'http://external-domain.com',
|
|
111
|
-
};
|
|
112
|
-
expect(testValidateThemeConfig({algolia})).toEqual({
|
|
113
|
-
algolia: {
|
|
114
|
-
...DEFAULT_CONFIG,
|
|
115
|
-
...algolia,
|
|
116
|
-
},
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test('searchParameters.facetFilters search config', () => {
|
|
121
|
-
const algolia = {
|
|
122
|
-
indexName: 'index',
|
|
123
|
-
apiKey: 'apiKey',
|
|
124
|
-
searchParameters: {
|
|
125
|
-
facetFilters: ['version:1.0'],
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
expect(testValidateThemeConfig({algolia})).toEqual({
|
|
129
|
-
algolia: {
|
|
130
|
-
...DEFAULT_CONFIG,
|
|
131
|
-
...algolia,
|
|
132
|
-
},
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
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
|
-
import {useHistory} from '@docusaurus/router';
|
|
9
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
10
|
-
import {useCallback, useEffect, useState} from 'react';
|
|
11
|
-
import type {SearchQuery} from '@theme/hooks/useSearchQuery';
|
|
12
|
-
|
|
13
|
-
const SEARCH_PARAM_QUERY = 'q';
|
|
14
|
-
|
|
15
|
-
function useSearchQuery(): SearchQuery {
|
|
16
|
-
const history = useHistory();
|
|
17
|
-
const {
|
|
18
|
-
siteConfig: {baseUrl},
|
|
19
|
-
} = useDocusaurusContext();
|
|
20
|
-
|
|
21
|
-
const [searchQuery, setSearchQueryState] = useState('');
|
|
22
|
-
|
|
23
|
-
// Init search query just after React hydration
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
const searchQueryStringValue =
|
|
26
|
-
new URLSearchParams(window.location.search).get(SEARCH_PARAM_QUERY) ?? '';
|
|
27
|
-
|
|
28
|
-
setSearchQueryState(searchQueryStringValue);
|
|
29
|
-
}, []);
|
|
30
|
-
|
|
31
|
-
const setSearchQuery = useCallback(
|
|
32
|
-
(newSearchQuery: string) => {
|
|
33
|
-
const searchParams = new URLSearchParams(window.location.search);
|
|
34
|
-
|
|
35
|
-
if (newSearchQuery) {
|
|
36
|
-
searchParams.set(SEARCH_PARAM_QUERY, newSearchQuery);
|
|
37
|
-
} else {
|
|
38
|
-
searchParams.delete(SEARCH_PARAM_QUERY);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
history.replace({
|
|
42
|
-
search: searchParams.toString(),
|
|
43
|
-
});
|
|
44
|
-
setSearchQueryState(newSearchQuery);
|
|
45
|
-
},
|
|
46
|
-
[history],
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const generateSearchPageLink = useCallback(
|
|
50
|
-
(targetSearchQuery: string) =>
|
|
51
|
-
// Refer to https://github.com/facebook/docusaurus/pull/2838
|
|
52
|
-
`${baseUrl}search?q=${encodeURIComponent(targetSearchQuery)}`,
|
|
53
|
-
[baseUrl],
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
searchQuery,
|
|
58
|
-
setSearchQuery,
|
|
59
|
-
generateSearchPageLink,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export default useSearchQuery;
|
package/tsconfig.browser.json
DELETED
package/tsconfig.json
DELETED
package/tsconfig.server.json
DELETED