@docusaurus/theme-search-algolia 0.0.0-5416 → 0.0.0-5426
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 +2 -0
- package/lib/client/index.js +2 -0
- package/lib/client/useAlgoliaThemeConfig.d.ts +2 -0
- package/lib/client/useAlgoliaThemeConfig.js +11 -0
- package/lib/client/useSearchResultUrlProcessor.d.ts +11 -0
- package/lib/client/useSearchResultUrlProcessor.js +33 -0
- package/lib/theme/SearchBar/index.js +15 -22
- package/lib/theme/SearchPage/index.js +15 -15
- package/lib/validateThemeConfig.js +13 -0
- package/package.json +10 -10
- package/src/client/index.ts +2 -0
- package/src/client/useAlgoliaThemeConfig.ts +15 -0
- package/src/client/useSearchResultUrlProcessor.ts +54 -0
- package/src/theme/SearchBar/index.tsx +16 -24
- package/src/theme/SearchPage/index.tsx +15 -18
- package/src/theme-search-algolia.d.ts +10 -0
- package/src/validateThemeConfig.ts +14 -0
package/lib/client/index.d.ts
CHANGED
|
@@ -4,4 +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
|
+
export { useAlgoliaThemeConfig } from './useAlgoliaThemeConfig';
|
|
7
8
|
export { useAlgoliaContextualFacetFilters } from './useAlgoliaContextualFacetFilters';
|
|
9
|
+
export { useSearchResultUrlProcessor } from './useSearchResultUrlProcessor';
|
package/lib/client/index.js
CHANGED
|
@@ -4,4 +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
|
+
export { useAlgoliaThemeConfig } from './useAlgoliaThemeConfig';
|
|
7
8
|
export { useAlgoliaContextualFacetFilters } from './useAlgoliaContextualFacetFilters';
|
|
9
|
+
export { useSearchResultUrlProcessor } from './useSearchResultUrlProcessor';
|
|
@@ -0,0 +1,11 @@
|
|
|
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 useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
8
|
+
export function useAlgoliaThemeConfig() {
|
|
9
|
+
const { siteConfig: { themeConfig }, } = useDocusaurusContext();
|
|
10
|
+
return themeConfig;
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
* Process the search result url from Algolia to its final form, ready to be
|
|
9
|
+
* navigated to or used as a link
|
|
10
|
+
*/
|
|
11
|
+
export declare function useSearchResultUrlProcessor(): (url: string) => string;
|
|
@@ -0,0 +1,33 @@
|
|
|
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 { useCallback } from 'react';
|
|
8
|
+
import { isRegexpStringMatch } from '@docusaurus/theme-common';
|
|
9
|
+
import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
|
|
10
|
+
import { useAlgoliaThemeConfig } from './useAlgoliaThemeConfig';
|
|
11
|
+
function replacePathname(pathname, replaceSearchResultPathname) {
|
|
12
|
+
return replaceSearchResultPathname
|
|
13
|
+
? pathname.replaceAll(new RegExp(replaceSearchResultPathname.from, 'g'), replaceSearchResultPathname.to)
|
|
14
|
+
: pathname;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Process the search result url from Algolia to its final form, ready to be
|
|
18
|
+
* navigated to or used as a link
|
|
19
|
+
*/
|
|
20
|
+
export function useSearchResultUrlProcessor() {
|
|
21
|
+
const { withBaseUrl } = useBaseUrlUtils();
|
|
22
|
+
const { algolia: { externalUrlRegex, replaceSearchResultPathname }, } = useAlgoliaThemeConfig();
|
|
23
|
+
return useCallback((url) => {
|
|
24
|
+
const parsedURL = new URL(url);
|
|
25
|
+
// Algolia contains an external domain => navigate to URL
|
|
26
|
+
if (isRegexpStringMatch(externalUrlRegex, parsedURL.href)) {
|
|
27
|
+
return url;
|
|
28
|
+
}
|
|
29
|
+
// Otherwise => transform to relative URL for SPA navigation
|
|
30
|
+
const relativeUrl = `${parsedURL.pathname + parsedURL.hash}`;
|
|
31
|
+
return withBaseUrl(replacePathname(relativeUrl, replaceSearchResultPathname));
|
|
32
|
+
}, [withBaseUrl, externalUrlRegex, replaceSearchResultPathname]);
|
|
33
|
+
}
|
|
@@ -4,18 +4,20 @@
|
|
|
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 React, {
|
|
8
|
-
import {
|
|
9
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
10
|
-
import {useHistory} from '@docusaurus/router';
|
|
11
|
-
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
12
|
-
import Link from '@docusaurus/Link';
|
|
7
|
+
import React, {useCallback, useMemo, useRef, useState} from 'react';
|
|
8
|
+
import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react';
|
|
13
9
|
import Head from '@docusaurus/Head';
|
|
10
|
+
import Link from '@docusaurus/Link';
|
|
11
|
+
import {useHistory} from '@docusaurus/router';
|
|
14
12
|
import {isRegexpStringMatch} from '@docusaurus/theme-common';
|
|
15
13
|
import {useSearchPage} from '@docusaurus/theme-common/internal';
|
|
16
|
-
import {
|
|
17
|
-
|
|
14
|
+
import {
|
|
15
|
+
useAlgoliaContextualFacetFilters,
|
|
16
|
+
useSearchResultUrlProcessor,
|
|
17
|
+
} from '@docusaurus/theme-search-algolia/client';
|
|
18
18
|
import Translate from '@docusaurus/Translate';
|
|
19
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
20
|
+
import {createPortal} from 'react-dom';
|
|
19
21
|
import translations from '@theme/SearchTranslations';
|
|
20
22
|
let DocSearchModal = null;
|
|
21
23
|
function Hit({hit, children}) {
|
|
@@ -39,6 +41,7 @@ function mergeFacetFilters(f1, f2) {
|
|
|
39
41
|
}
|
|
40
42
|
function DocSearch({contextualSearch, externalUrlRegex, ...props}) {
|
|
41
43
|
const {siteMetadata} = useDocusaurusContext();
|
|
44
|
+
const processSearchResultUrl = useSearchResultUrlProcessor();
|
|
42
45
|
const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters();
|
|
43
46
|
const configFacetFilters = props.searchParameters?.facetFilters ?? [];
|
|
44
47
|
const facetFilters = contextualSearch
|
|
@@ -51,7 +54,6 @@ function DocSearch({contextualSearch, externalUrlRegex, ...props}) {
|
|
|
51
54
|
...props.searchParameters,
|
|
52
55
|
facetFilters,
|
|
53
56
|
};
|
|
54
|
-
const {withBaseUrl} = useBaseUrlUtils();
|
|
55
57
|
const history = useHistory();
|
|
56
58
|
const searchContainer = useRef(null);
|
|
57
59
|
const searchButtonRef = useRef(null);
|
|
@@ -104,19 +106,10 @@ function DocSearch({contextualSearch, externalUrlRegex, ...props}) {
|
|
|
104
106
|
},
|
|
105
107
|
}).current;
|
|
106
108
|
const transformItems = useRef((items) =>
|
|
107
|
-
items.map((item) => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return item;
|
|
112
|
-
}
|
|
113
|
-
// We transform the absolute URL into a relative URL.
|
|
114
|
-
const url = new URL(item.url);
|
|
115
|
-
return {
|
|
116
|
-
...item,
|
|
117
|
-
url: withBaseUrl(`${url.pathname}${url.hash}`),
|
|
118
|
-
};
|
|
119
|
-
}),
|
|
109
|
+
items.map((item) => ({
|
|
110
|
+
...item,
|
|
111
|
+
url: processSearchResultUrl(item.url),
|
|
112
|
+
})),
|
|
120
113
|
).current;
|
|
121
114
|
const resultsFooterComponent = useMemo(
|
|
122
115
|
() =>
|
|
@@ -5,26 +5,29 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
/* eslint-disable jsx-a11y/no-autofocus */
|
|
8
|
-
import React, {useEffect,
|
|
8
|
+
import React, {useEffect, useReducer, useRef, useState} from 'react';
|
|
9
9
|
import clsx from 'clsx';
|
|
10
|
-
import algoliaSearch from 'algoliasearch/lite';
|
|
11
10
|
import algoliaSearchHelper from 'algoliasearch-helper';
|
|
11
|
+
import algoliaSearch from 'algoliasearch/lite';
|
|
12
|
+
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
12
13
|
import Head from '@docusaurus/Head';
|
|
13
14
|
import Link from '@docusaurus/Link';
|
|
14
|
-
import
|
|
15
|
+
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
15
16
|
import {
|
|
16
17
|
HtmlClassNameProvider,
|
|
17
|
-
usePluralForm,
|
|
18
|
-
isRegexpStringMatch,
|
|
19
18
|
useEvent,
|
|
19
|
+
usePluralForm,
|
|
20
20
|
} from '@docusaurus/theme-common';
|
|
21
21
|
import {
|
|
22
|
-
useTitleFormatter,
|
|
23
22
|
useSearchPage,
|
|
23
|
+
useTitleFormatter,
|
|
24
24
|
} from '@docusaurus/theme-common/internal';
|
|
25
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
26
|
-
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
27
25
|
import Translate, {translate} from '@docusaurus/Translate';
|
|
26
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
27
|
+
import {
|
|
28
|
+
useAlgoliaThemeConfig,
|
|
29
|
+
useSearchResultUrlProcessor,
|
|
30
|
+
} from '@docusaurus/theme-search-algolia/client';
|
|
28
31
|
import Layout from '@theme/Layout';
|
|
29
32
|
import styles from './styles.module.css';
|
|
30
33
|
// Very simple pluralization: probably good enough for now
|
|
@@ -114,12 +117,12 @@ function SearchVersionSelectList({docsSearchVersionsHelpers}) {
|
|
|
114
117
|
}
|
|
115
118
|
function SearchPageContent() {
|
|
116
119
|
const {
|
|
117
|
-
siteConfig: {themeConfig},
|
|
118
120
|
i18n: {currentLocale},
|
|
119
121
|
} = useDocusaurusContext();
|
|
120
122
|
const {
|
|
121
|
-
algolia: {appId, apiKey, indexName
|
|
122
|
-
} =
|
|
123
|
+
algolia: {appId, apiKey, indexName},
|
|
124
|
+
} = useAlgoliaThemeConfig();
|
|
125
|
+
const processSearchResultUrl = useSearchResultUrlProcessor();
|
|
123
126
|
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
124
127
|
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
125
128
|
const {searchQuery, setSearchQuery} = useSearchPage();
|
|
@@ -191,15 +194,12 @@ function SearchPageContent() {
|
|
|
191
194
|
_highlightResult: {hierarchy},
|
|
192
195
|
_snippetResult: snippet = {},
|
|
193
196
|
}) => {
|
|
194
|
-
const parsedURL = new URL(url);
|
|
195
197
|
const titles = Object.keys(hierarchy).map((key) =>
|
|
196
198
|
sanitizeValue(hierarchy[key].value),
|
|
197
199
|
);
|
|
198
200
|
return {
|
|
199
201
|
title: titles.pop(),
|
|
200
|
-
url:
|
|
201
|
-
? parsedURL.href
|
|
202
|
-
: parsedURL.pathname + parsedURL.hash,
|
|
202
|
+
url: processSearchResultUrl(url),
|
|
203
203
|
summary: snippet.content
|
|
204
204
|
? `${sanitizeValue(snippet.content.value)}...`
|
|
205
205
|
: '',
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.validateThemeConfig = exports.Schema = exports.DEFAULT_CONFIG = void 0;
|
|
10
|
+
const utils_1 = require("@docusaurus/utils");
|
|
10
11
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
12
|
exports.DEFAULT_CONFIG = {
|
|
12
13
|
// Enabled by default, as it makes sense in most cases
|
|
@@ -33,6 +34,18 @@ exports.Schema = utils_validation_1.Joi.object({
|
|
|
33
34
|
.try(utils_validation_1.Joi.boolean().invalid(true), utils_validation_1.Joi.string())
|
|
34
35
|
.allow(null)
|
|
35
36
|
.default(exports.DEFAULT_CONFIG.searchPagePath),
|
|
37
|
+
replaceSearchResultPathname: utils_validation_1.Joi.object({
|
|
38
|
+
from: utils_validation_1.Joi.custom((from) => {
|
|
39
|
+
if (typeof from === 'string') {
|
|
40
|
+
return (0, utils_1.escapeRegexp)(from);
|
|
41
|
+
}
|
|
42
|
+
else if (from instanceof RegExp) {
|
|
43
|
+
return from.source;
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`it should be a RegExp or a string, but received ${from}`);
|
|
46
|
+
}).required(),
|
|
47
|
+
to: utils_validation_1.Joi.string().required(),
|
|
48
|
+
}).optional(),
|
|
36
49
|
})
|
|
37
50
|
.label('themeConfig.algolia')
|
|
38
51
|
.required()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/theme-search-algolia",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-5426",
|
|
4
4
|
"description": "Algolia search component for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"sideEffects": [
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@docsearch/react": "^3.2.1",
|
|
37
|
-
"@docusaurus/core": "0.0.0-
|
|
38
|
-
"@docusaurus/logger": "0.0.0-
|
|
39
|
-
"@docusaurus/plugin-content-docs": "0.0.0-
|
|
40
|
-
"@docusaurus/theme-common": "0.0.0-
|
|
41
|
-
"@docusaurus/theme-translations": "0.0.0-
|
|
42
|
-
"@docusaurus/utils": "0.0.0-
|
|
43
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
37
|
+
"@docusaurus/core": "0.0.0-5426",
|
|
38
|
+
"@docusaurus/logger": "0.0.0-5426",
|
|
39
|
+
"@docusaurus/plugin-content-docs": "0.0.0-5426",
|
|
40
|
+
"@docusaurus/theme-common": "0.0.0-5426",
|
|
41
|
+
"@docusaurus/theme-translations": "0.0.0-5426",
|
|
42
|
+
"@docusaurus/utils": "0.0.0-5426",
|
|
43
|
+
"@docusaurus/utils-validation": "0.0.0-5426",
|
|
44
44
|
"algoliasearch": "^4.14.2",
|
|
45
45
|
"algoliasearch-helper": "^3.11.0",
|
|
46
46
|
"clsx": "^1.2.1",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"utility-types": "^3.10.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@docusaurus/module-type-aliases": "0.0.0-
|
|
54
|
+
"@docusaurus/module-type-aliases": "0.0.0-5426"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"react": "^16.8.4 || ^17.0.0",
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"engines": {
|
|
61
61
|
"node": ">=16.14"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "7bc998a32c3cd26e76d79b8f7e276b06bc11af02"
|
|
64
64
|
}
|
package/src/client/index.ts
CHANGED
|
@@ -5,4 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
export {useAlgoliaThemeConfig} from './useAlgoliaThemeConfig';
|
|
8
9
|
export {useAlgoliaContextualFacetFilters} from './useAlgoliaContextualFacetFilters';
|
|
10
|
+
export {useSearchResultUrlProcessor} from './useSearchResultUrlProcessor';
|
|
@@ -0,0 +1,15 @@
|
|
|
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 useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
8
|
+
import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
|
|
9
|
+
|
|
10
|
+
export function useAlgoliaThemeConfig(): ThemeConfig {
|
|
11
|
+
const {
|
|
12
|
+
siteConfig: {themeConfig},
|
|
13
|
+
} = useDocusaurusContext();
|
|
14
|
+
return themeConfig as ThemeConfig;
|
|
15
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
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 {useCallback} from 'react';
|
|
9
|
+
import {isRegexpStringMatch} from '@docusaurus/theme-common';
|
|
10
|
+
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
11
|
+
import {useAlgoliaThemeConfig} from './useAlgoliaThemeConfig';
|
|
12
|
+
import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
|
|
13
|
+
|
|
14
|
+
function replacePathname(
|
|
15
|
+
pathname: string,
|
|
16
|
+
replaceSearchResultPathname: ThemeConfig['algolia']['replaceSearchResultPathname'],
|
|
17
|
+
): string {
|
|
18
|
+
return replaceSearchResultPathname
|
|
19
|
+
? pathname.replaceAll(
|
|
20
|
+
new RegExp(replaceSearchResultPathname.from, 'g'),
|
|
21
|
+
replaceSearchResultPathname.to,
|
|
22
|
+
)
|
|
23
|
+
: pathname;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Process the search result url from Algolia to its final form, ready to be
|
|
28
|
+
* navigated to or used as a link
|
|
29
|
+
*/
|
|
30
|
+
export function useSearchResultUrlProcessor(): (url: string) => string {
|
|
31
|
+
const {withBaseUrl} = useBaseUrlUtils();
|
|
32
|
+
const {
|
|
33
|
+
algolia: {externalUrlRegex, replaceSearchResultPathname},
|
|
34
|
+
} = useAlgoliaThemeConfig();
|
|
35
|
+
|
|
36
|
+
return useCallback(
|
|
37
|
+
(url: string) => {
|
|
38
|
+
const parsedURL = new URL(url);
|
|
39
|
+
|
|
40
|
+
// Algolia contains an external domain => navigate to URL
|
|
41
|
+
if (isRegexpStringMatch(externalUrlRegex, parsedURL.href)) {
|
|
42
|
+
return url;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Otherwise => transform to relative URL for SPA navigation
|
|
46
|
+
const relativeUrl = `${parsedURL.pathname + parsedURL.hash}`;
|
|
47
|
+
|
|
48
|
+
return withBaseUrl(
|
|
49
|
+
replacePathname(relativeUrl, replaceSearchResultPathname),
|
|
50
|
+
);
|
|
51
|
+
},
|
|
52
|
+
[withBaseUrl, externalUrlRegex, replaceSearchResultPathname],
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -5,20 +5,23 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React, {
|
|
9
|
-
import {
|
|
10
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
11
|
-
import {useHistory} from '@docusaurus/router';
|
|
12
|
-
import {useBaseUrlUtils} from '@docusaurus/useBaseUrl';
|
|
13
|
-
import Link from '@docusaurus/Link';
|
|
8
|
+
import React, {useCallback, useMemo, useRef, useState} from 'react';
|
|
9
|
+
import {DocSearchButton, useDocSearchKeyboardEvents} from '@docsearch/react';
|
|
14
10
|
import Head from '@docusaurus/Head';
|
|
11
|
+
import Link from '@docusaurus/Link';
|
|
12
|
+
import {useHistory} from '@docusaurus/router';
|
|
15
13
|
import {isRegexpStringMatch} from '@docusaurus/theme-common';
|
|
16
14
|
import {useSearchPage} from '@docusaurus/theme-common/internal';
|
|
17
|
-
import {
|
|
18
|
-
|
|
15
|
+
import {
|
|
16
|
+
useAlgoliaContextualFacetFilters,
|
|
17
|
+
useSearchResultUrlProcessor,
|
|
18
|
+
} from '@docusaurus/theme-search-algolia/client';
|
|
19
19
|
import Translate from '@docusaurus/Translate';
|
|
20
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
21
|
+
import {createPortal} from 'react-dom';
|
|
20
22
|
import translations from '@theme/SearchTranslations';
|
|
21
23
|
|
|
24
|
+
import type {AutocompleteState} from '@algolia/autocomplete-core';
|
|
22
25
|
import type {
|
|
23
26
|
DocSearchModal as DocSearchModalType,
|
|
24
27
|
DocSearchModalProps,
|
|
@@ -28,7 +31,6 @@ import type {
|
|
|
28
31
|
StoredDocSearchHit,
|
|
29
32
|
} from '@docsearch/react/dist/esm/types';
|
|
30
33
|
import type {SearchClient} from 'algoliasearch/lite';
|
|
31
|
-
import type {AutocompleteState} from '@algolia/autocomplete-core';
|
|
32
34
|
|
|
33
35
|
type DocSearchProps = Omit<
|
|
34
36
|
DocSearchModalProps,
|
|
@@ -88,6 +90,7 @@ function DocSearch({
|
|
|
88
90
|
...props
|
|
89
91
|
}: DocSearchProps) {
|
|
90
92
|
const {siteMetadata} = useDocusaurusContext();
|
|
93
|
+
const processSearchResultUrl = useSearchResultUrlProcessor();
|
|
91
94
|
|
|
92
95
|
const contextualSearchFacetFilters =
|
|
93
96
|
useAlgoliaContextualFacetFilters() as FacetFilters;
|
|
@@ -107,7 +110,6 @@ function DocSearch({
|
|
|
107
110
|
facetFilters,
|
|
108
111
|
};
|
|
109
112
|
|
|
110
|
-
const {withBaseUrl} = useBaseUrlUtils();
|
|
111
113
|
const history = useHistory();
|
|
112
114
|
const searchContainer = useRef<HTMLDivElement | null>(null);
|
|
113
115
|
const searchButtonRef = useRef<HTMLButtonElement>(null);
|
|
@@ -172,20 +174,10 @@ function DocSearch({
|
|
|
172
174
|
|
|
173
175
|
const transformItems = useRef<DocSearchModalProps['transformItems']>(
|
|
174
176
|
(items) =>
|
|
175
|
-
items.map((item) => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
return item;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// We transform the absolute URL into a relative URL.
|
|
183
|
-
const url = new URL(item.url);
|
|
184
|
-
return {
|
|
185
|
-
...item,
|
|
186
|
-
url: withBaseUrl(`${url.pathname}${url.hash}`),
|
|
187
|
-
};
|
|
188
|
-
}),
|
|
177
|
+
items.map((item) => ({
|
|
178
|
+
...item,
|
|
179
|
+
url: processSearchResultUrl(item.url),
|
|
180
|
+
})),
|
|
189
181
|
).current;
|
|
190
182
|
|
|
191
183
|
const resultsFooterComponent: DocSearchProps['resultsFooterComponent'] =
|
|
@@ -7,32 +7,33 @@
|
|
|
7
7
|
|
|
8
8
|
/* eslint-disable jsx-a11y/no-autofocus */
|
|
9
9
|
|
|
10
|
-
import React, {useEffect,
|
|
10
|
+
import React, {useEffect, useReducer, useRef, useState} from 'react';
|
|
11
11
|
import clsx from 'clsx';
|
|
12
12
|
|
|
13
|
-
import algoliaSearch from 'algoliasearch/lite';
|
|
14
13
|
import algoliaSearchHelper from 'algoliasearch-helper';
|
|
14
|
+
import algoliaSearch from 'algoliasearch/lite';
|
|
15
15
|
|
|
16
|
+
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
|
|
16
17
|
import Head from '@docusaurus/Head';
|
|
17
18
|
import Link from '@docusaurus/Link';
|
|
18
|
-
import
|
|
19
|
+
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
19
20
|
import {
|
|
20
21
|
HtmlClassNameProvider,
|
|
21
|
-
usePluralForm,
|
|
22
|
-
isRegexpStringMatch,
|
|
23
22
|
useEvent,
|
|
23
|
+
usePluralForm,
|
|
24
24
|
} from '@docusaurus/theme-common';
|
|
25
25
|
import {
|
|
26
|
-
useTitleFormatter,
|
|
27
26
|
useSearchPage,
|
|
27
|
+
useTitleFormatter,
|
|
28
28
|
} from '@docusaurus/theme-common/internal';
|
|
29
|
-
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
30
|
-
import {useAllDocsData} from '@docusaurus/plugin-content-docs/client';
|
|
31
29
|
import Translate, {translate} from '@docusaurus/Translate';
|
|
30
|
+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
31
|
+
import {
|
|
32
|
+
useAlgoliaThemeConfig,
|
|
33
|
+
useSearchResultUrlProcessor,
|
|
34
|
+
} from '@docusaurus/theme-search-algolia/client';
|
|
32
35
|
import Layout from '@theme/Layout';
|
|
33
36
|
|
|
34
|
-
import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
|
|
35
|
-
|
|
36
37
|
import styles from './styles.module.css';
|
|
37
38
|
|
|
38
39
|
// Very simple pluralization: probably good enough for now
|
|
@@ -157,12 +158,12 @@ type ResultDispatcher =
|
|
|
157
158
|
|
|
158
159
|
function SearchPageContent(): JSX.Element {
|
|
159
160
|
const {
|
|
160
|
-
siteConfig: {themeConfig},
|
|
161
161
|
i18n: {currentLocale},
|
|
162
162
|
} = useDocusaurusContext();
|
|
163
163
|
const {
|
|
164
|
-
algolia: {appId, apiKey, indexName
|
|
165
|
-
} =
|
|
164
|
+
algolia: {appId, apiKey, indexName},
|
|
165
|
+
} = useAlgoliaThemeConfig();
|
|
166
|
+
const processSearchResultUrl = useSearchResultUrlProcessor();
|
|
166
167
|
const documentsFoundPlural = useDocumentsFoundPlural();
|
|
167
168
|
|
|
168
169
|
const docsSearchVersionsHelpers = useDocsSearchVersionsHelpers();
|
|
@@ -245,16 +246,12 @@ function SearchPageContent(): JSX.Element {
|
|
|
245
246
|
_highlightResult: {hierarchy: {[key: string]: {value: string}}};
|
|
246
247
|
_snippetResult: {content?: {value: string}};
|
|
247
248
|
}) => {
|
|
248
|
-
const parsedURL = new URL(url);
|
|
249
249
|
const titles = Object.keys(hierarchy).map((key) =>
|
|
250
250
|
sanitizeValue(hierarchy[key]!.value),
|
|
251
251
|
);
|
|
252
|
-
|
|
253
252
|
return {
|
|
254
253
|
title: titles.pop()!,
|
|
255
|
-
url:
|
|
256
|
-
? parsedURL.href
|
|
257
|
-
: parsedURL.pathname + parsedURL.hash,
|
|
254
|
+
url: processSearchResultUrl(url),
|
|
258
255
|
summary: snippet.content
|
|
259
256
|
? `${sanitizeValue(snippet.content.value)}...`
|
|
260
257
|
: '',
|
|
@@ -17,13 +17,23 @@ declare module '@docusaurus/theme-search-algolia' {
|
|
|
17
17
|
indexName: string;
|
|
18
18
|
searchParameters: {[key: string]: unknown};
|
|
19
19
|
searchPagePath: string | false | null;
|
|
20
|
+
replaceSearchResultPathname?: {
|
|
21
|
+
from: string;
|
|
22
|
+
to: string;
|
|
23
|
+
};
|
|
20
24
|
};
|
|
21
25
|
};
|
|
22
26
|
export type UserThemeConfig = DeepPartial<ThemeConfig>;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
declare module '@docusaurus/theme-search-algolia/client' {
|
|
30
|
+
import type {ThemeConfig} from '@docusaurus/theme-search-algolia';
|
|
31
|
+
|
|
32
|
+
export function useAlgoliaThemeConfig(): ThemeConfig;
|
|
33
|
+
|
|
26
34
|
export function useAlgoliaContextualFacetFilters(): [string, string[]];
|
|
35
|
+
|
|
36
|
+
export function useSearchResultUrlProcessor(): (url: string) => string;
|
|
27
37
|
}
|
|
28
38
|
|
|
29
39
|
declare module '@theme/SearchPage' {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import {escapeRegexp} from '@docusaurus/utils';
|
|
8
9
|
import {Joi} from '@docusaurus/utils-validation';
|
|
9
10
|
import type {
|
|
10
11
|
ThemeConfig,
|
|
@@ -39,6 +40,19 @@ export const Schema = Joi.object<ThemeConfig>({
|
|
|
39
40
|
.try(Joi.boolean().invalid(true), Joi.string())
|
|
40
41
|
.allow(null)
|
|
41
42
|
.default(DEFAULT_CONFIG.searchPagePath),
|
|
43
|
+
replaceSearchResultPathname: Joi.object({
|
|
44
|
+
from: Joi.custom((from) => {
|
|
45
|
+
if (typeof from === 'string') {
|
|
46
|
+
return escapeRegexp(from);
|
|
47
|
+
} else if (from instanceof RegExp) {
|
|
48
|
+
return from.source;
|
|
49
|
+
}
|
|
50
|
+
throw new Error(
|
|
51
|
+
`it should be a RegExp or a string, but received ${from}`,
|
|
52
|
+
);
|
|
53
|
+
}).required(),
|
|
54
|
+
to: Joi.string().required(),
|
|
55
|
+
}).optional(),
|
|
42
56
|
})
|
|
43
57
|
.label('themeConfig.algolia')
|
|
44
58
|
.required()
|