@easyops-cn/docusaurus-search-local 0.32.1 → 0.33.1
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/CHANGELOG.md +14 -0
- package/dist/client/client/theme/SearchBar/SearchBar.jsx +38 -11
- package/dist/client/client/theme/SearchBar/fetchIndexes.js +12 -2
- package/dist/client/client/theme/SearchPage/SearchPage.jsx +3 -3
- package/dist/client/client/theme/hooks/useSearchQuery.js +10 -4
- package/dist/client/client/utils/__mocks__/proxiedGenerated.js +1 -1
- package/dist/client/index.js +1 -0
- package/dist/server/index.js +2 -0
- package/dist/server/server/utils/generate.js +7 -3
- package/dist/server/server/utils/postBuildFactory.js +49 -4
- package/dist/server/server/utils/validateOptions.js +2 -0
- package/dist/types/index.d.ts +152 -0
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [0.33.1](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.33.0...v0.33.1) (2022-10-17)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* refine search context, support `hideSearchBarWithNoSearchContext` ([38908ed](https://github.com/easyops-cn/docusaurus-search-local/commit/38908edd8dea6bbf5a38f2ea225f9a9530b406ed))
|
|
11
|
+
|
|
12
|
+
## [0.33.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.32.1...v0.33.0) (2022-10-16)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* support search context by paths ([aa6de9a](https://github.com/easyops-cn/docusaurus-search-local/commit/aa6de9a2890cad2570bd40f41cccb0626a5163d6))
|
|
18
|
+
|
|
5
19
|
## [0.32.1](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.32.0...v0.32.1) (2022-10-08)
|
|
6
20
|
|
|
7
21
|
|
|
@@ -10,7 +10,7 @@ import { fetchIndexes } from "./fetchIndexes";
|
|
|
10
10
|
import { SearchSourceFactory } from "../../utils/SearchSourceFactory";
|
|
11
11
|
import { SuggestionTemplate } from "./SuggestionTemplate";
|
|
12
12
|
import { EmptyTemplate } from "./EmptyTemplate";
|
|
13
|
-
import { searchResultLimits, Mark, searchBarShortcut, searchBarShortcutHint, searchBarPosition, docsPluginIdForPreferredVersion, indexDocs, } from "../../utils/proxiedGenerated";
|
|
13
|
+
import { searchResultLimits, Mark, searchBarShortcut, searchBarShortcutHint, searchBarPosition, docsPluginIdForPreferredVersion, indexDocs, searchContextByPaths, hideSearchBarWithNoSearchContext, } from "../../utils/proxiedGenerated";
|
|
14
14
|
import LoadingRing from "../LoadingRing/LoadingRing";
|
|
15
15
|
import styles from "./SearchBar.module.css";
|
|
16
16
|
async function fetchAutoCompleteJS() {
|
|
@@ -59,22 +59,47 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
59
59
|
const history = useHistory();
|
|
60
60
|
const location = useLocation();
|
|
61
61
|
const searchBarRef = useRef(null);
|
|
62
|
-
const
|
|
62
|
+
const indexStateMap = useRef(new Map());
|
|
63
63
|
// Should the input be focused after the index is loaded?
|
|
64
64
|
const focusAfterIndexLoaded = useRef(false);
|
|
65
65
|
const [loading, setLoading] = useState(false);
|
|
66
66
|
const [inputChanged, setInputChanged] = useState(false);
|
|
67
67
|
const [inputValue, setInputValue] = useState("");
|
|
68
68
|
const search = useRef(null);
|
|
69
|
+
const prevSearchContext = useRef("");
|
|
70
|
+
const [searchContext, setSearchContext] = useState("");
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!Array.isArray(searchContextByPaths)) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
let nextSearchContext = "";
|
|
76
|
+
if (location.pathname.startsWith(versionUrl)) {
|
|
77
|
+
const uri = location.pathname.substring(versionUrl.length);
|
|
78
|
+
const matchedPath = searchContextByPaths.find((path) => uri === path || uri.startsWith(`${path}/`));
|
|
79
|
+
if (matchedPath) {
|
|
80
|
+
nextSearchContext = matchedPath;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (prevSearchContext.current !== nextSearchContext) {
|
|
84
|
+
// Reset index state map once search context is changed.
|
|
85
|
+
indexStateMap.current.delete(nextSearchContext);
|
|
86
|
+
prevSearchContext.current = nextSearchContext;
|
|
87
|
+
}
|
|
88
|
+
setSearchContext(nextSearchContext);
|
|
89
|
+
}, [location.pathname, versionUrl]);
|
|
90
|
+
const hidden = !!hideSearchBarWithNoSearchContext &&
|
|
91
|
+
Array.isArray(searchContextByPaths) &&
|
|
92
|
+
searchContext === "";
|
|
69
93
|
const loadIndex = useCallback(async () => {
|
|
70
|
-
if (
|
|
94
|
+
if (hidden || indexStateMap.current.get(searchContext)) {
|
|
71
95
|
// Do not load the index (again) if its already loaded or in the process of being loaded.
|
|
72
96
|
return;
|
|
73
97
|
}
|
|
74
|
-
|
|
98
|
+
indexStateMap.current.set(searchContext, "loading");
|
|
99
|
+
search.current?.autocomplete.destroy();
|
|
75
100
|
setLoading(true);
|
|
76
101
|
const [{ wrappedIndexes, zhDictionary }, autoComplete] = await Promise.all([
|
|
77
|
-
fetchIndexes(versionUrl),
|
|
102
|
+
fetchIndexes(versionUrl, searchContext),
|
|
78
103
|
fetchAutoCompleteJS(),
|
|
79
104
|
]);
|
|
80
105
|
search.current = autoComplete(searchBarRef.current, {
|
|
@@ -106,7 +131,9 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
106
131
|
return;
|
|
107
132
|
}
|
|
108
133
|
const a = document.createElement("a");
|
|
109
|
-
const url = `${baseUrl}search?q=${encodeURIComponent(query)}
|
|
134
|
+
const url = `${baseUrl}search?q=${encodeURIComponent(query)}${Array.isArray(searchContextByPaths)
|
|
135
|
+
? `&ctx=${encodeURIComponent(searchContext)}`
|
|
136
|
+
: ""}`;
|
|
110
137
|
a.href = url;
|
|
111
138
|
a.textContent = translate({
|
|
112
139
|
id: "theme.SearchBar.seeAll",
|
|
@@ -115,7 +142,7 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
115
142
|
a.addEventListener("click", (e) => {
|
|
116
143
|
if (!e.ctrlKey && !e.metaKey) {
|
|
117
144
|
e.preventDefault();
|
|
118
|
-
search.current
|
|
145
|
+
search.current?.autocomplete.close();
|
|
119
146
|
history.push(url);
|
|
120
147
|
}
|
|
121
148
|
});
|
|
@@ -145,16 +172,16 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
145
172
|
.on("autocomplete:closed", () => {
|
|
146
173
|
searchBarRef.current?.blur();
|
|
147
174
|
});
|
|
148
|
-
|
|
175
|
+
indexStateMap.current.set(searchContext, "done");
|
|
149
176
|
setLoading(false);
|
|
150
177
|
if (focusAfterIndexLoaded.current) {
|
|
151
178
|
const input = searchBarRef.current;
|
|
152
179
|
if (input.value) {
|
|
153
|
-
search.current
|
|
180
|
+
search.current?.autocomplete.open();
|
|
154
181
|
}
|
|
155
182
|
input.focus();
|
|
156
183
|
}
|
|
157
|
-
}, [
|
|
184
|
+
}, [hidden, searchContext, versionUrl, baseUrl, history]);
|
|
158
185
|
useEffect(() => {
|
|
159
186
|
if (!Mark) {
|
|
160
187
|
return;
|
|
@@ -239,7 +266,7 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
239
266
|
return (<div className={clsx("navbar__search", styles.searchBarContainer, {
|
|
240
267
|
[styles.searchIndexLoading]: loading && inputChanged,
|
|
241
268
|
[styles.focused]: focused,
|
|
242
|
-
})}>
|
|
269
|
+
})} hidden={hidden}>
|
|
243
270
|
<input placeholder={translate({
|
|
244
271
|
id: "theme.SearchBar.label",
|
|
245
272
|
message: "Search",
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import lunr from "lunr";
|
|
2
2
|
import { searchIndexUrl } from "../../utils/proxiedGenerated";
|
|
3
|
-
|
|
3
|
+
const cache = new Map();
|
|
4
|
+
export function fetchIndexes(baseUrl, searchContext) {
|
|
5
|
+
const cacheKey = `${baseUrl}${searchContext}`;
|
|
6
|
+
let promise = cache.get(cacheKey);
|
|
7
|
+
if (!promise) {
|
|
8
|
+
promise = legacyFetchIndexes(baseUrl, searchContext);
|
|
9
|
+
cache.set(cacheKey, promise);
|
|
10
|
+
}
|
|
11
|
+
return promise;
|
|
12
|
+
}
|
|
13
|
+
export async function legacyFetchIndexes(baseUrl, searchContext) {
|
|
4
14
|
if (process.env.NODE_ENV === "production") {
|
|
5
|
-
const json = (await (await fetch(`${baseUrl}${searchIndexUrl}`)).json());
|
|
15
|
+
const json = (await (await fetch(`${baseUrl}${searchIndexUrl.replace("{dir}", searchContext ? `-${searchContext.replace(/\//g, "-")}` : "")}`)).json());
|
|
6
16
|
const wrappedIndexes = json.map(({ documents, index }, type) => ({
|
|
7
17
|
type: type,
|
|
8
18
|
documents,
|
|
@@ -48,7 +48,7 @@ function SearchPageContent() {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
const { selectMessage } = usePluralForm();
|
|
51
|
-
const { searchValue, updateSearchPath } = useSearchQuery();
|
|
51
|
+
const { searchValue, searchContext, updateSearchPath } = useSearchQuery();
|
|
52
52
|
const [searchQuery, setSearchQuery] = useState(searchValue);
|
|
53
53
|
const [searchSource, setSearchSource] = useState();
|
|
54
54
|
const [searchResults, setSearchResults] = useState();
|
|
@@ -90,11 +90,11 @@ function SearchPageContent() {
|
|
|
90
90
|
}, [searchValue]);
|
|
91
91
|
useEffect(() => {
|
|
92
92
|
async function doFetchIndexes() {
|
|
93
|
-
const { wrappedIndexes, zhDictionary } = await fetchIndexes(versionUrl);
|
|
93
|
+
const { wrappedIndexes, zhDictionary } = await fetchIndexes(versionUrl, searchContext);
|
|
94
94
|
setSearchSource(() => SearchSourceFactory(wrappedIndexes, zhDictionary, 100));
|
|
95
95
|
}
|
|
96
96
|
doFetchIndexes();
|
|
97
|
-
}, [versionUrl]);
|
|
97
|
+
}, [searchContext, versionUrl]);
|
|
98
98
|
return (<React.Fragment>
|
|
99
99
|
<Head>
|
|
100
100
|
{/*
|
|
@@ -7,15 +7,19 @@
|
|
|
7
7
|
import { useHistory, useLocation } from "@docusaurus/router";
|
|
8
8
|
import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
|
|
9
9
|
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
10
|
+
import { searchContextByPaths, } from "../../utils/proxiedGenerated";
|
|
10
11
|
const SEARCH_PARAM_QUERY = "q";
|
|
12
|
+
const SEARCH_PARAM_CONTEXT = "ctx";
|
|
11
13
|
function useSearchQuery() {
|
|
12
14
|
const history = useHistory();
|
|
13
15
|
const location = useLocation();
|
|
14
16
|
const { siteConfig: { baseUrl }, } = useDocusaurusContext();
|
|
17
|
+
const params = ExecutionEnvironment.canUseDOM ? new URLSearchParams(location.search) : null;
|
|
18
|
+
const searchValue = params?.get(SEARCH_PARAM_QUERY) || "";
|
|
19
|
+
const searchContext = params?.get(SEARCH_PARAM_CONTEXT) || "";
|
|
15
20
|
return {
|
|
16
|
-
searchValue
|
|
17
|
-
|
|
18
|
-
"",
|
|
21
|
+
searchValue,
|
|
22
|
+
searchContext,
|
|
19
23
|
updateSearchPath: (searchValue) => {
|
|
20
24
|
const searchParams = new URLSearchParams(location.search);
|
|
21
25
|
if (searchValue) {
|
|
@@ -29,8 +33,10 @@ function useSearchQuery() {
|
|
|
29
33
|
});
|
|
30
34
|
},
|
|
31
35
|
generateSearchPageLink: (searchValue) => {
|
|
36
|
+
const searchParams = new URLSearchParams(location.search);
|
|
37
|
+
const searchContext = searchParams.get(SEARCH_PARAM_CONTEXT) || "";
|
|
32
38
|
// Refer to https://github.com/facebook/docusaurus/pull/2838
|
|
33
|
-
return `${baseUrl}search?q=${encodeURIComponent(searchValue)}`;
|
|
39
|
+
return `${baseUrl}search?q=${encodeURIComponent(searchValue)}${Array.isArray(searchContextByPaths) ? `&ctx=${encodeURIComponent(searchContext)}` : ""}`;
|
|
34
40
|
},
|
|
35
41
|
};
|
|
36
42
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export let language = ["en", "zh"];
|
|
2
2
|
export let removeDefaultStopWordFilter = false;
|
|
3
3
|
export let removeDefaultStemmer = false;
|
|
4
|
-
export const searchIndexUrl = "search-index.json?_=abc";
|
|
4
|
+
export const searchIndexUrl = "search-index{dir}.json?_=abc";
|
|
5
5
|
export const searchResultLimits = 8;
|
|
6
6
|
export const searchResultContextMaxLength = 50;
|
|
7
7
|
export const explicitSearchResultPath = false;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,7 +6,7 @@ const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
|
6
6
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
7
|
const getIndexHash_1 = require("./getIndexHash");
|
|
8
8
|
function generate(config, dir) {
|
|
9
|
-
const { language, removeDefaultStopWordFilter, removeDefaultStemmer, highlightSearchTermsOnTargetPage, searchResultLimits, searchResultContextMaxLength, explicitSearchResultPath, searchBarShortcut, searchBarShortcutHint, searchBarPosition, docsPluginIdForPreferredVersion, indexDocs, } = config;
|
|
9
|
+
const { language, removeDefaultStopWordFilter, removeDefaultStemmer, highlightSearchTermsOnTargetPage, searchResultLimits, searchResultContextMaxLength, explicitSearchResultPath, searchBarShortcut, searchBarShortcutHint, searchBarPosition, docsPluginIdForPreferredVersion, indexDocs, searchContextByPaths, hideSearchBarWithNoSearchContext, } = config;
|
|
10
10
|
const indexHash = (0, getIndexHash_1.getIndexHash)(config);
|
|
11
11
|
const contents = [
|
|
12
12
|
`import lunr from ${JSON.stringify(require.resolve("lunr"))};`,
|
|
@@ -35,11 +35,11 @@ function generate(config, dir) {
|
|
|
35
35
|
else {
|
|
36
36
|
contents.push("export const Mark = null;");
|
|
37
37
|
}
|
|
38
|
-
let searchIndexFilename = "search-index.json";
|
|
38
|
+
let searchIndexFilename = "search-index{dir}.json";
|
|
39
39
|
let searchIndexQuery = "";
|
|
40
40
|
if (indexHash) {
|
|
41
41
|
if (config.hashed === "filename") {
|
|
42
|
-
searchIndexFilename = `search-index-${indexHash}.json`;
|
|
42
|
+
searchIndexFilename = `search-index{dir}-${indexHash}.json`;
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
45
|
searchIndexQuery = `?_=${indexHash}`;
|
|
@@ -56,6 +56,10 @@ function generate(config, dir) {
|
|
|
56
56
|
? "undefined"
|
|
57
57
|
: JSON.stringify(docsPluginIdForPreferredVersion)};`);
|
|
58
58
|
contents.push(`export const indexDocs = ${JSON.stringify(indexDocs)};`);
|
|
59
|
+
contents.push(`export const searchContextByPaths = ${JSON.stringify(Array.isArray(searchContextByPaths) && searchContextByPaths.length > 0
|
|
60
|
+
? searchContextByPaths
|
|
61
|
+
: null)};`);
|
|
62
|
+
contents.push(`export const hideSearchBarWithNoSearchContext = ${JSON.stringify(!!hideSearchBarWithNoSearchContext)};`);
|
|
59
63
|
fs_1.default.writeFileSync(path_1.default.join(dir, "generated.js"), contents.join("\n"));
|
|
60
64
|
return searchIndexFilename;
|
|
61
65
|
}
|
|
@@ -20,10 +20,55 @@ function postBuildFactory(config, searchIndexFilename) {
|
|
|
20
20
|
// Give every index entry a unique id so that the index does not need to store long URLs.
|
|
21
21
|
const allDocuments = yield (0, scanDocuments_1.scanDocuments)(versionData.paths);
|
|
22
22
|
(0, debug_1.debugInfo)("building index");
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const docsByDirMap = new Map();
|
|
24
|
+
const { searchContextByPaths, hideSearchBarWithNoSearchContext } = config;
|
|
25
|
+
if (searchContextByPaths) {
|
|
26
|
+
const { baseUrl } = buildData;
|
|
27
|
+
const rootAllDocs = [];
|
|
28
|
+
if (!hideSearchBarWithNoSearchContext) {
|
|
29
|
+
docsByDirMap.set("", rootAllDocs);
|
|
30
|
+
}
|
|
31
|
+
let docIndex = 0;
|
|
32
|
+
for (const documents of allDocuments) {
|
|
33
|
+
rootAllDocs[docIndex] = [];
|
|
34
|
+
for (const doc of documents) {
|
|
35
|
+
if (doc.u.startsWith(baseUrl)) {
|
|
36
|
+
const uri = doc.u.substring(baseUrl.length);
|
|
37
|
+
const matchedPath = searchContextByPaths.find((path) => uri === path || uri.startsWith(`${path}/`));
|
|
38
|
+
if (matchedPath) {
|
|
39
|
+
let dirAllDocs = docsByDirMap.get(matchedPath);
|
|
40
|
+
if (!dirAllDocs) {
|
|
41
|
+
dirAllDocs = [];
|
|
42
|
+
docsByDirMap.set(matchedPath, dirAllDocs);
|
|
43
|
+
}
|
|
44
|
+
let dirDocs = dirAllDocs[docIndex];
|
|
45
|
+
if (!dirDocs) {
|
|
46
|
+
dirAllDocs[docIndex] = dirDocs = [];
|
|
47
|
+
}
|
|
48
|
+
dirDocs.push(doc);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
rootAllDocs[docIndex].push(doc);
|
|
53
|
+
}
|
|
54
|
+
docIndex++;
|
|
55
|
+
}
|
|
56
|
+
for (const [k, v] of docsByDirMap) {
|
|
57
|
+
const docsNotEmpty = v.filter((d) => !!d);
|
|
58
|
+
if (docsNotEmpty.length < v.length) {
|
|
59
|
+
docsByDirMap.set(k, docsNotEmpty);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
docsByDirMap.set("", allDocuments);
|
|
65
|
+
}
|
|
66
|
+
for (const [k, allDocs] of docsByDirMap) {
|
|
67
|
+
const searchIndex = (0, buildIndex_1.buildIndex)(allDocs, config);
|
|
68
|
+
(0, debug_1.debugInfo)(`writing index (/${k}) to disk`);
|
|
69
|
+
yield writeFileAsync(path_1.default.join(versionData.outDir, searchIndexFilename.replace("{dir}", k === "" ? "" : `-${k.replace(/\//g, "-")}`)), JSON.stringify(searchIndex), { encoding: "utf8" });
|
|
70
|
+
(0, debug_1.debugInfo)(`index (/${k}) written to disk successfully!`);
|
|
71
|
+
}
|
|
27
72
|
}
|
|
28
73
|
});
|
|
29
74
|
};
|
|
@@ -28,6 +28,8 @@ const schema = utils_validation_1.Joi.object({
|
|
|
28
28
|
docsPluginIdForPreferredVersion: utils_validation_1.Joi.string(),
|
|
29
29
|
zhUserDict: utils_validation_1.Joi.string(),
|
|
30
30
|
zhUserDictPath: utils_validation_1.Joi.string(),
|
|
31
|
+
searchContextByPaths: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()),
|
|
32
|
+
hideSearchBarWithNoSearchContext: utils_validation_1.Joi.boolean().default(false),
|
|
31
33
|
});
|
|
32
34
|
function validateOptions({ options, validate, }) {
|
|
33
35
|
return validate(schema, options || {});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
export interface PluginOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Whether to index docs.
|
|
4
|
+
*
|
|
5
|
+
* @default true
|
|
6
|
+
*/
|
|
7
|
+
indexDocs?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Whether to index blog.
|
|
10
|
+
*
|
|
11
|
+
* @default true
|
|
12
|
+
*/
|
|
13
|
+
indexBlog?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to index pages.
|
|
16
|
+
*
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
indexPages?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Base route path(s) of docs. Slash at beginning is not required.
|
|
22
|
+
*
|
|
23
|
+
* Note: for [docs-only mode](https://docusaurus.io/docs/docs-introduction#docs-only-mode),
|
|
24
|
+
* this needs to be the same as `routeBasePath` in your `@docusaurus/preset-classic` config e.g., `"/"`.
|
|
25
|
+
*
|
|
26
|
+
* @default "/docs"
|
|
27
|
+
*/
|
|
28
|
+
docsRouteBasePath?: string | string[];
|
|
29
|
+
/**
|
|
30
|
+
* Base route path(s) of blog. Slash at beginning is not required.
|
|
31
|
+
*
|
|
32
|
+
* @default "/blog"
|
|
33
|
+
*/
|
|
34
|
+
blogRouteBasePath?: string | string[];
|
|
35
|
+
/**
|
|
36
|
+
* All [lunr-languages](https://github.com/MihaiValentin/lunr-languages) supported languages, + `zh` 🔥.
|
|
37
|
+
*/
|
|
38
|
+
language?: string | string[];
|
|
39
|
+
/**
|
|
40
|
+
* Whether to add a hashed query when fetching index (based on the content hash of all indexed
|
|
41
|
+
* `*.md` in `docsDir` and `blogDir` if applicable). Setting to `"filename"` will save hash in
|
|
42
|
+
* filename instead of query.
|
|
43
|
+
*
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
hashed?: boolean | "query" | "filename";
|
|
47
|
+
/**
|
|
48
|
+
* The dir(s) of docs to get the content hash, it's relative to the dir of your project.
|
|
49
|
+
*
|
|
50
|
+
* @default "docs"
|
|
51
|
+
*/
|
|
52
|
+
docsDir?: string | string[];
|
|
53
|
+
/**
|
|
54
|
+
* The dir(s) of blog to get the content hash, it's relative to the dir of your project.
|
|
55
|
+
*
|
|
56
|
+
* @default "blog"
|
|
57
|
+
*/
|
|
58
|
+
blogDir?: string | string[];
|
|
59
|
+
/**
|
|
60
|
+
* When you're using multi-instance of docs, set the docs plugin id which you'd like to
|
|
61
|
+
* check the preferred version with, for the search index.
|
|
62
|
+
*/
|
|
63
|
+
docsPluginIdForPreferredVersion?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Sometimes people (E.g., us) want to keep the English stop words as indexed, since they
|
|
66
|
+
* maybe are relevant in programming docs.
|
|
67
|
+
*/
|
|
68
|
+
removeDefaultStopWordFilter?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Enable this if you want to be able to search for any partial word at the cost of search performance.
|
|
71
|
+
*
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
removeDefaultStemmer?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Highlight search terms on target page.
|
|
77
|
+
*
|
|
78
|
+
* @default false
|
|
79
|
+
*/
|
|
80
|
+
highlightSearchTermsOnTargetPage?: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Limit the search results.
|
|
83
|
+
*
|
|
84
|
+
* @default 8
|
|
85
|
+
*/
|
|
86
|
+
searchResultLimits?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Set the max length of characters of each search result to show.
|
|
89
|
+
*
|
|
90
|
+
* @default 50
|
|
91
|
+
*/
|
|
92
|
+
searchResultContextMaxLength?: number;
|
|
93
|
+
/**
|
|
94
|
+
* Whether an explicit path to a heading should be presented on a suggestion template.
|
|
95
|
+
*
|
|
96
|
+
* @default false
|
|
97
|
+
*/
|
|
98
|
+
explicitSearchResultPath?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Set the match rules to ignore some routes. Put a string if you want an exact match,
|
|
101
|
+
* or put a regex if you want a partial match. Note: without the website base url.
|
|
102
|
+
*
|
|
103
|
+
* @default []
|
|
104
|
+
*/
|
|
105
|
+
ignoreFiles?: string | RegExp | (string | RegExp)[];
|
|
106
|
+
/**
|
|
107
|
+
* Whether to enable keyboard shortcut to focus in search bar.
|
|
108
|
+
*
|
|
109
|
+
* @default true
|
|
110
|
+
*/
|
|
111
|
+
searchBarShortcut?: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Whether to show keyboard shortcut hint in search bar. Disable it if you need to
|
|
114
|
+
* hide the hint while shortcut is still enabled.
|
|
115
|
+
*
|
|
116
|
+
* @default true
|
|
117
|
+
*/
|
|
118
|
+
searchBarShortcutHint?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* The side of the navbar the search bar should appear on. By default,
|
|
121
|
+
* it will try to autodetect based on your docusaurus config according
|
|
122
|
+
* to [the docs](https://docusaurus.io/docs/api/themes/configuration#navbar-search).
|
|
123
|
+
*
|
|
124
|
+
* @default "auto"
|
|
125
|
+
*/
|
|
126
|
+
searchBarPosition?: "auto" | "left" | "right";
|
|
127
|
+
/**
|
|
128
|
+
* Provide your custom dict for language of zh,
|
|
129
|
+
* [see here](https://github.com/fxsjy/jieba#%E8%BD%BD%E5%85%A5%E8%AF%8D%E5%85%B8)
|
|
130
|
+
*/
|
|
131
|
+
zhUserDict?: string;
|
|
132
|
+
/**
|
|
133
|
+
* Provide the file path to your custom dict for language of zh,
|
|
134
|
+
* E.g.: `path.resolve("./src/zh-dict.txt")`
|
|
135
|
+
*/
|
|
136
|
+
zhUserDictPath?: string;
|
|
137
|
+
/**
|
|
138
|
+
* Provide an list of sub-paths as separate search context, E.g.: `["docs", "community", "legacy/resources"]`.
|
|
139
|
+
* It will create multiple search indexes by these paths.
|
|
140
|
+
*/
|
|
141
|
+
searchContextByPaths?: string[];
|
|
142
|
+
/**
|
|
143
|
+
* Whether to hide the search bar when no search context was matched.
|
|
144
|
+
*
|
|
145
|
+
* By default, if `searchContextByPaths` is set, pages which are not matched with it will be considered
|
|
146
|
+
* as with a search context of ROOT. By setting `hideSearchBarWithNoSearchContext` to false, these pages
|
|
147
|
+
* will be considered as with NO search context, and the search bar will be hidden.
|
|
148
|
+
*
|
|
149
|
+
* @default false
|
|
150
|
+
*/
|
|
151
|
+
hideSearchBarWithNoSearchContext?: boolean;
|
|
152
|
+
}
|
package/package.json
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easyops-cn/docusaurus-search-local",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"description": "An offline/local search plugin for Docusaurus v2",
|
|
5
5
|
"repository": "https://github.com/easyops-cn/docusaurus-search-local",
|
|
6
6
|
"homepage": "https://github.com/easyops-cn/docusaurus-search-local",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"start": "concurrently -k -n client,server \"yarn run start:client\" \"yarn run start:server\"",
|
|
8
|
+
"start": "concurrently -k -n client,server,types \"yarn run start:client\" \"yarn run start:server\" \"yarn run start:types\"",
|
|
9
9
|
"start:client": "tsc --watch --project tsconfig.client.json",
|
|
10
10
|
"start:server": "tsc --watch --project tsconfig.server.json",
|
|
11
|
-
"
|
|
11
|
+
"start:types": "tsc --project tsconfig.types.json --watch",
|
|
12
|
+
"build": "rimraf dist && yarn run build:client && yarn run build:server && yarn run build:types && yarn run copy-static-files",
|
|
12
13
|
"build:client": "tsc --project tsconfig.client.json",
|
|
13
14
|
"build:server": "tsc --project tsconfig.server.json",
|
|
15
|
+
"build:types": "tsc --project tsconfig.types.json",
|
|
14
16
|
"copy-static-files": "copyfiles -u 3 \"src/client/theme/**/*.css\" dist/client/client/theme && copyfiles -u 1 \"locales/*.json\" dist/locales"
|
|
15
17
|
},
|
|
16
18
|
"main": "dist/server/server/index.js",
|
|
19
|
+
"typings": "dist/types/index.d.ts",
|
|
17
20
|
"files": [
|
|
18
21
|
"/dist",
|
|
19
22
|
"!/dist/generated.js"
|