@easyops-cn/docusaurus-search-local 0.26.1 → 0.27.2
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 +24 -3
- package/README.md +1 -0
- package/dist/client/client/theme/SearchBar/SearchBar.jsx +20 -5
- package/dist/client/client/theme/SearchPage/SearchPage.jsx +19 -5
- package/dist/server/server/utils/postBuildFactory.js +9 -7
- package/dist/server/server/utils/processDocInfos.js +78 -44
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,18 +2,39 @@
|
|
|
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
|
-
|
|
5
|
+
## [0.27.2](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.27.1...v0.27.2) (2022-06-21)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* search page for non latest doc versions ([15f6161](https://github.com/easyops-cn/docusaurus-search-local/commit/15f61612f8d59dde0ba401e15d76d080865d8e8b))
|
|
11
|
+
* use the active plugin id when getting the current docs version ([824e134](https://github.com/easyops-cn/docusaurus-search-local/commit/824e1347f3f571b45e1e39f708ffd75c01f13339))
|
|
12
|
+
* fix active plugin may be undefined ([0bfbbb2](https://github.com/easyops-cn/docusaurus-search-local/commit/0bfbbb29cee66fcbb3be589da226caef6210fa5a))
|
|
13
|
+
* make `@docusaurus/theme-common` as peer ([68dc812](https://github.com/easyops-cn/docusaurus-search-local/commit/68dc812c84451c68dc9f9448c4a2b39a3f8f3bcc))
|
|
14
|
+
|
|
15
|
+
## [0.27.1](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.27.0...v0.27.1) (2022-06-13)
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
- properly support no trailing slashes after fixing indexing top level pages ([999bd8b](https://github.com/easyops-cn/docusaurus-search-local/commit/999bd8bec8abe73f12abe20f58f8030be46c9ecd)), closes [#212](https://github.com/easyops-cn/docusaurus-search-local/issues/212)
|
|
6
20
|
|
|
21
|
+
## [0.27.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.26.1...v0.27.0) (2022-05-29)
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
- versioned search ([6865e7c](https://github.com/easyops-cn/docusaurus-search-local/commit/6865e7c3eee416e53648877359cdf206119be043)), closes [#66](https://github.com/easyops-cn/docusaurus-search-local/issues/66)
|
|
26
|
+
|
|
27
|
+
### [0.26.1](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.26.0...v0.26.1) (2022-05-25)
|
|
7
28
|
|
|
8
29
|
### Bug Fixes
|
|
9
30
|
|
|
10
|
-
|
|
31
|
+
- fix i18n id of `theme.SearchPage.noResultsText` ([fe530f3](https://github.com/easyops-cn/docusaurus-search-local/commit/fe530f35da0b11c78c9d68cb6a7fea5871919e00))
|
|
11
32
|
|
|
12
33
|
## [0.26.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.26.0...v0.26.0) (2022-05-24)
|
|
13
34
|
|
|
14
35
|
### Features
|
|
15
36
|
|
|
16
|
-
|
|
37
|
+
- add a clear button to the search bar [#170](https://github.com/easyops-cn/docusaurus-search-local/issues/170) ([f516123](https://github.com/easyops-cn/docusaurus-search-local/commit/f5161238cb7466fe7309e9166037d681e647f910))
|
|
17
38
|
|
|
18
39
|
## [0.25.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.24.1...v0.25.0) (2022-05-19)
|
|
19
40
|
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
See https://github.com/easyops-cn/docusaurus-search-local#readme
|
|
@@ -4,6 +4,8 @@ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
|
4
4
|
import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
|
|
5
5
|
import { useHistory, useLocation } from "@docusaurus/router";
|
|
6
6
|
import { translate } from "@docusaurus/Translate";
|
|
7
|
+
import { useDocsPreferredVersion } from "@docusaurus/theme-common";
|
|
8
|
+
import { useActivePlugin } from "@docusaurus/plugin-content-docs/client";
|
|
7
9
|
import { fetchIndexes } from "./fetchIndexes";
|
|
8
10
|
import { SearchSourceFactory } from "../../utils/SearchSourceFactory";
|
|
9
11
|
import { SuggestionTemplate } from "./SuggestionTemplate";
|
|
@@ -27,6 +29,17 @@ async function fetchAutoCompleteJS() {
|
|
|
27
29
|
const SEARCH_PARAM_HIGHLIGHT = "_highlight";
|
|
28
30
|
export default function SearchBar({ handleSearchBarToggle, }) {
|
|
29
31
|
const { siteConfig: { baseUrl }, } = useDocusaurusContext();
|
|
32
|
+
// It returns undefined for non-docs pages
|
|
33
|
+
const activePlugin = useActivePlugin();
|
|
34
|
+
let versionUrl = baseUrl;
|
|
35
|
+
// For non-docs pages while using plugin-content-docs with custom ids,
|
|
36
|
+
// this will throw an error of:
|
|
37
|
+
// > Docusaurus plugin global data not found for "docusaurus-plugin-content-docs" plugin with id "default".
|
|
38
|
+
// It seems that we can not get the correct id for non-docs pages.
|
|
39
|
+
const { preferredVersion } = useDocsPreferredVersion(activePlugin?.pluginId);
|
|
40
|
+
if (preferredVersion && !preferredVersion.isLast) {
|
|
41
|
+
versionUrl = preferredVersion.path + "/";
|
|
42
|
+
}
|
|
30
43
|
const history = useHistory();
|
|
31
44
|
const location = useLocation();
|
|
32
45
|
const searchBarRef = useRef(null);
|
|
@@ -45,7 +58,7 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
45
58
|
indexState.current = "loading";
|
|
46
59
|
setLoading(true);
|
|
47
60
|
const [{ wrappedIndexes, zhDictionary }, autoComplete] = await Promise.all([
|
|
48
|
-
fetchIndexes(
|
|
61
|
+
fetchIndexes(versionUrl),
|
|
49
62
|
fetchAutoCompleteJS(),
|
|
50
63
|
]);
|
|
51
64
|
search.current = autoComplete(searchBarRef.current, {
|
|
@@ -123,7 +136,7 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
123
136
|
}
|
|
124
137
|
input.focus();
|
|
125
138
|
}
|
|
126
|
-
}, [baseUrl, history]);
|
|
139
|
+
}, [baseUrl, versionUrl, history]);
|
|
127
140
|
useEffect(() => {
|
|
128
141
|
if (!Mark) {
|
|
129
142
|
return;
|
|
@@ -188,15 +201,17 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
188
201
|
const onClearSearch = useCallback(() => {
|
|
189
202
|
const params = new URLSearchParams(location.search);
|
|
190
203
|
params.delete(SEARCH_PARAM_HIGHLIGHT);
|
|
191
|
-
|
|
192
|
-
|
|
204
|
+
const paramsStr = params.toString();
|
|
205
|
+
const searchUrl = location.pathname +
|
|
206
|
+
(paramsStr != "" ? `?${paramsStr}` : "") +
|
|
207
|
+
location.hash;
|
|
193
208
|
if (searchUrl != location.pathname + location.search + location.hash) {
|
|
194
209
|
history.push(searchUrl);
|
|
195
210
|
}
|
|
196
211
|
// We always clear these here because in case no match was selected the above history push wont happen
|
|
197
212
|
setInputValue("");
|
|
198
213
|
search.current?.autocomplete.setVal("");
|
|
199
|
-
}, [location.pathname, location.search, location.hash]);
|
|
214
|
+
}, [location.pathname, location.search, location.hash, history]);
|
|
200
215
|
return (<div className={clsx("navbar__search", styles.searchBarContainer, {
|
|
201
216
|
[styles.searchIndexLoading]: loading && inputChanged,
|
|
202
217
|
})}>
|
|
@@ -4,7 +4,8 @@ import Layout from "@theme/Layout";
|
|
|
4
4
|
import Head from "@docusaurus/Head";
|
|
5
5
|
import Link from "@docusaurus/Link";
|
|
6
6
|
import { translate } from "@docusaurus/Translate";
|
|
7
|
-
import { usePluralForm } from "@docusaurus/theme-common";
|
|
7
|
+
import { usePluralForm, useDocsPreferredVersion, } from "@docusaurus/theme-common";
|
|
8
|
+
import { useActivePlugin } from "@docusaurus/plugin-content-docs/client";
|
|
8
9
|
import useSearchQuery from "../hooks/useSearchQuery";
|
|
9
10
|
import { fetchIndexes } from "../SearchBar/fetchIndexes";
|
|
10
11
|
import { SearchSourceFactory } from "../../utils/SearchSourceFactory";
|
|
@@ -15,7 +16,20 @@ import LoadingRing from "../LoadingRing/LoadingRing";
|
|
|
15
16
|
import styles from "./SearchPage.module.css";
|
|
16
17
|
import { concatDocumentPath } from "../../utils/concatDocumentPath";
|
|
17
18
|
export default function SearchPage() {
|
|
19
|
+
return (<Layout>
|
|
20
|
+
<SearchPageContent />
|
|
21
|
+
</Layout>);
|
|
22
|
+
}
|
|
23
|
+
function SearchPageContent() {
|
|
18
24
|
const { siteConfig: { baseUrl }, } = useDocusaurusContext();
|
|
25
|
+
// It returns undefined for non-docs pages.
|
|
26
|
+
const activePlugin = useActivePlugin();
|
|
27
|
+
let versionUrl = baseUrl;
|
|
28
|
+
// There is an issue, see `SearchBar.tsx`.
|
|
29
|
+
const { preferredVersion } = useDocsPreferredVersion(activePlugin?.pluginId);
|
|
30
|
+
if (preferredVersion && !preferredVersion.isLast) {
|
|
31
|
+
versionUrl = preferredVersion.path + "/";
|
|
32
|
+
}
|
|
19
33
|
const { selectMessage } = usePluralForm();
|
|
20
34
|
const { searchValue, updateSearchPath } = useSearchQuery();
|
|
21
35
|
const [searchQuery, setSearchQuery] = useState(searchValue);
|
|
@@ -59,12 +73,12 @@ export default function SearchPage() {
|
|
|
59
73
|
}, [searchValue]);
|
|
60
74
|
useEffect(() => {
|
|
61
75
|
async function doFetchIndexes() {
|
|
62
|
-
const { wrappedIndexes, zhDictionary } = await fetchIndexes(
|
|
76
|
+
const { wrappedIndexes, zhDictionary } = await fetchIndexes(versionUrl);
|
|
63
77
|
setSearchSource(() => SearchSourceFactory(wrappedIndexes, zhDictionary, 100));
|
|
64
78
|
}
|
|
65
79
|
doFetchIndexes();
|
|
66
|
-
}, [
|
|
67
|
-
return (<
|
|
80
|
+
}, [versionUrl]);
|
|
81
|
+
return (<React.Fragment>
|
|
68
82
|
<Head>
|
|
69
83
|
{/*
|
|
70
84
|
We should not index search pages
|
|
@@ -106,7 +120,7 @@ export default function SearchPage() {
|
|
|
106
120
|
searchResults.map((item) => (<SearchResultItem key={item.document.i} searchResult={item}/>))}
|
|
107
121
|
</section>
|
|
108
122
|
</div>
|
|
109
|
-
</
|
|
123
|
+
</React.Fragment>);
|
|
110
124
|
}
|
|
111
125
|
function SearchResultItem({ searchResult: { document, type, page, tokens, metadata }, }) {
|
|
112
126
|
const isTitle = type === 0;
|
|
@@ -16,13 +16,15 @@ function postBuildFactory(config) {
|
|
|
16
16
|
(0, debug_1.debugInfo)("gathering documents");
|
|
17
17
|
const data = (0, processDocInfos_1.processDocInfos)(buildData, config);
|
|
18
18
|
(0, debug_1.debugInfo)("parsing documents");
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
for (let versionData of data) {
|
|
20
|
+
// Give every index entry a unique id so that the index does not need to store long URLs.
|
|
21
|
+
const allDocuments = yield (0, scanDocuments_1.scanDocuments)(versionData.paths);
|
|
22
|
+
(0, debug_1.debugInfo)("building index");
|
|
23
|
+
const searchIndex = (0, buildIndex_1.buildIndex)(allDocuments, config);
|
|
24
|
+
(0, debug_1.debugInfo)("writing index to disk");
|
|
25
|
+
yield writeFileAsync(path_1.default.join(versionData.outDir, "search-index.json"), JSON.stringify(searchIndex), { encoding: "utf8" });
|
|
26
|
+
(0, debug_1.debugInfo)("index written to disk successfully!");
|
|
27
|
+
}
|
|
26
28
|
});
|
|
27
29
|
};
|
|
28
30
|
}
|
|
@@ -3,55 +3,89 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.processDocInfos = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
6
|
-
function processDocInfos({ routesPaths, outDir, baseUrl, siteConfig }, { indexDocs, indexBlog, indexPages, docsRouteBasePath, blogRouteBasePath, ignoreFiles, }) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
function processDocInfos({ routesPaths, outDir, baseUrl, siteConfig, plugins }, { indexDocs, indexBlog, indexPages, docsRouteBasePath, blogRouteBasePath, ignoreFiles, }) {
|
|
7
|
+
const emptySet = new Set();
|
|
8
|
+
let versionData = [{ versionOutDir: outDir, docs: emptySet }];
|
|
9
|
+
if (plugins) {
|
|
10
|
+
const docsPluginData = plugins.find((element) => element.name === "docusaurus-plugin-content-docs");
|
|
11
|
+
if (docsPluginData) {
|
|
12
|
+
versionData = [];
|
|
13
|
+
const loadedVersions = docsPluginData.content.loadedVersions;
|
|
14
|
+
for (const loadedVersion of loadedVersions) {
|
|
15
|
+
const docs = new Set();
|
|
16
|
+
for (const doc of loadedVersion.docs) {
|
|
17
|
+
docs.add(doc.permalink);
|
|
18
|
+
}
|
|
19
|
+
const route = loadedVersion.path.substr(baseUrl.length);
|
|
20
|
+
let versionOutDir = outDir;
|
|
21
|
+
// The last versions search-index should always be placed in the root since it is the one used from non-docs pages
|
|
22
|
+
if (!loadedVersion.isLast) {
|
|
23
|
+
versionOutDir = path_1.default.join(outDir, ...route.split("/").filter((i) => i));
|
|
24
|
+
}
|
|
25
|
+
versionData.push({ versionOutDir, docs });
|
|
24
26
|
}
|
|
25
|
-
return route.match(reg);
|
|
26
|
-
})) {
|
|
27
|
-
return;
|
|
28
27
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
}
|
|
29
|
+
// Create a list of files to index per document version. This will always include all pages and blogs.
|
|
30
|
+
const result = [];
|
|
31
|
+
for (const { versionOutDir, docs } of versionData) {
|
|
32
|
+
const versionPaths = routesPaths
|
|
33
|
+
.map((url) => {
|
|
34
|
+
// istanbul ignore next
|
|
35
|
+
if (!url.startsWith(baseUrl)) {
|
|
36
|
+
throw new Error(`The route must start with the baseUrl "${baseUrl}", but was "${url}". This is a bug, please report it.`);
|
|
37
|
+
}
|
|
38
|
+
const route = url.substr(baseUrl.length).replace(/\/$/, "");
|
|
39
|
+
// Do not index homepage, error page and search page.
|
|
40
|
+
if (((!docsRouteBasePath || docsRouteBasePath[0] !== "") &&
|
|
41
|
+
route === "") ||
|
|
42
|
+
route === "404.html" ||
|
|
43
|
+
route === "search") {
|
|
34
44
|
return;
|
|
35
45
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
// ignore files
|
|
47
|
+
if (ignoreFiles === null || ignoreFiles === void 0 ? void 0 : ignoreFiles.some((reg) => {
|
|
48
|
+
if (typeof reg === "string") {
|
|
49
|
+
return route === reg;
|
|
50
|
+
}
|
|
51
|
+
return route.match(reg);
|
|
52
|
+
})) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (indexBlog &&
|
|
56
|
+
blogRouteBasePath.some((basePath) => isSameOrSubRoute(route, basePath))) {
|
|
57
|
+
if (blogRouteBasePath.some((basePath) => isSameRoute(route, basePath) ||
|
|
58
|
+
isSameOrSubRoute(route, path_1.default.posix.join(basePath, "tags")))) {
|
|
59
|
+
// Do not index list of blog posts and tags filter pages
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
return { route, url, type: "blog" };
|
|
63
|
+
}
|
|
64
|
+
if (indexDocs &&
|
|
65
|
+
docsRouteBasePath.some((basePath) => isSameOrSubRoute(route, basePath))) {
|
|
66
|
+
if (docs.size === 0 || docs.has(url)) {
|
|
67
|
+
return { route, url, type: "docs" };
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (indexPages) {
|
|
72
|
+
return { route, url, type: "page" };
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
})
|
|
76
|
+
.filter(Boolean)
|
|
77
|
+
.map(({ route, url, type }) => ({
|
|
78
|
+
filePath: path_1.default.join(outDir, siteConfig.trailingSlash === false && route != ""
|
|
79
|
+
? `${route}.html`
|
|
80
|
+
: `${route}/index.html`),
|
|
81
|
+
url,
|
|
82
|
+
type,
|
|
83
|
+
}));
|
|
84
|
+
if (versionPaths.length > 0) {
|
|
85
|
+
result.push({ outDir: versionOutDir, paths: versionPaths });
|
|
44
86
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
.filter(Boolean)
|
|
48
|
-
.map(({ route, url, type }) => ({
|
|
49
|
-
filePath: path_1.default.join(outDir, siteConfig.trailingSlash === false
|
|
50
|
-
? `${route}.html`
|
|
51
|
-
: `${route}/index.html`),
|
|
52
|
-
url,
|
|
53
|
-
type,
|
|
54
|
-
}));
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
55
89
|
}
|
|
56
90
|
exports.processDocInfos = processDocInfos;
|
|
57
91
|
function isSameRoute(routeA, routeB) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easyops-cn/docusaurus-search-local",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.2",
|
|
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",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@docusaurus/
|
|
26
|
+
"@docusaurus/plugin-content-docs": "^2.0.0-beta.20",
|
|
27
27
|
"@docusaurus/theme-translations": "^2.0.0-beta.20",
|
|
28
28
|
"@docusaurus/utils": "^2.0.0-beta.20",
|
|
29
29
|
"@docusaurus/utils-common": "^2.0.0-beta.20",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@docusaurus/module-type-aliases": "^2.0.0-beta.20",
|
|
45
|
+
"@docusaurus/theme-common": "^2.0.0-beta.20",
|
|
45
46
|
"@docusaurus/types": "^2.0.0-beta.20",
|
|
46
47
|
"@tsconfig/docusaurus": "^1.0.2",
|
|
47
48
|
"@types/cheerio": "^0.22.31",
|
|
@@ -60,6 +61,8 @@
|
|
|
60
61
|
"typescript": "^4.6.4"
|
|
61
62
|
},
|
|
62
63
|
"peerDependencies": {
|
|
63
|
-
"
|
|
64
|
+
"@docusaurus/theme-common": "^2.0.0-beta.20",
|
|
65
|
+
"react": "^16.14.0 || ^17.0.0 || ^18.0.0",
|
|
66
|
+
"react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0"
|
|
64
67
|
}
|
|
65
68
|
}
|