@easyops-cn/docusaurus-search-local 0.34.0 → 0.36.0
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 +19 -0
- package/dist/client/client/theme/SearchBar/SearchBar.jsx +49 -31
- package/dist/client/client/theme/SearchPage/SearchPage.jsx +4 -3
- package/dist/client/client/theme/SearchPage/SearchPage.module.css +22 -1
- package/dist/server/server/utils/parse.js +6 -1
- package/dist/server/server/utils/postBuildFactory.js +1 -1
- package/dist/server/server/utils/processPluginOptions.js +1 -0
- package/dist/server/server/utils/scanDocuments.js +2 -2
- package/dist/server/server/utils/validateOptions.js +1 -0
- package/dist/types/index.d.ts +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
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.36.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.35.0...v0.36.0) (2023-09-09)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* added ignoreClasses option to be able to exclude specific content from indexing ([e9f7794](https://github.com/easyops-cn/docusaurus-search-local/commit/e9f7794f48c7af070c377d56bf3b6dbfccf3b9de))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* make tests work on windows ([565199a](https://github.com/easyops-cn/docusaurus-search-local/commit/565199a63760e51f2f5421c8df075aeeb7e54a53))
|
|
16
|
+
|
|
17
|
+
## [0.35.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.34.0...v0.35.0) (2023-03-04)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* improve no results UI when searching in context ([#323](https://github.com/easyops-cn/docusaurus-search-local/issues/323)) ([1a70835](https://github.com/easyops-cn/docusaurus-search-local/commit/1a708353d5fc6edae0f6e7d16bbd6e32381a9ea1))
|
|
23
|
+
|
|
5
24
|
## [0.34.0](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.33.6...v0.34.0) (2023-02-16)
|
|
6
25
|
|
|
7
26
|
|
|
@@ -102,6 +102,53 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
102
102
|
fetchIndexes(versionUrl, searchContext),
|
|
103
103
|
fetchAutoCompleteJS(),
|
|
104
104
|
]);
|
|
105
|
+
const searchFooterLinkElement = ({ query, isEmpty, }) => {
|
|
106
|
+
const a = document.createElement("a");
|
|
107
|
+
const params = new URLSearchParams();
|
|
108
|
+
const seeAllResultsText = translate({
|
|
109
|
+
id: "theme.SearchBar.seeAll",
|
|
110
|
+
message: "See all results",
|
|
111
|
+
});
|
|
112
|
+
const seeAllResultsOutsideContextText = translate({
|
|
113
|
+
id: "theme.SearchBar.seeAllOutsideContext",
|
|
114
|
+
message: "See results outside {context}",
|
|
115
|
+
}, { context: searchContext });
|
|
116
|
+
const seeAllResultsInContextText = translate({
|
|
117
|
+
id: "theme.SearchBar.searchInContext",
|
|
118
|
+
message: "See all results in {context}",
|
|
119
|
+
}, { context: searchContext });
|
|
120
|
+
params.set("q", query);
|
|
121
|
+
let linkText;
|
|
122
|
+
if (searchContext && isEmpty) {
|
|
123
|
+
linkText = seeAllResultsOutsideContextText;
|
|
124
|
+
}
|
|
125
|
+
else if (searchContext) {
|
|
126
|
+
linkText = seeAllResultsInContextText;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
linkText = seeAllResultsText;
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(searchContextByPaths) && !isEmpty) {
|
|
132
|
+
params.set("ctx", searchContext);
|
|
133
|
+
}
|
|
134
|
+
if (versionUrl !== baseUrl) {
|
|
135
|
+
if (!versionUrl.startsWith(baseUrl)) {
|
|
136
|
+
throw new Error(`Version url '${versionUrl}' does not start with base url '${baseUrl}', this is a bug of \`@easyops-cn/docusaurus-search-local\`, please report it.`);
|
|
137
|
+
}
|
|
138
|
+
params.set("version", versionUrl.substring(baseUrl.length));
|
|
139
|
+
}
|
|
140
|
+
const url = `${baseUrl}search?${params.toString()}`;
|
|
141
|
+
a.href = url;
|
|
142
|
+
a.textContent = linkText;
|
|
143
|
+
a.addEventListener("click", (e) => {
|
|
144
|
+
if (!e.ctrlKey && !e.metaKey) {
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
search.current?.autocomplete.close();
|
|
147
|
+
history.push(url);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return a;
|
|
151
|
+
};
|
|
105
152
|
search.current = autoComplete(searchBarRef.current, {
|
|
106
153
|
hint: false,
|
|
107
154
|
autoselect: true,
|
|
@@ -127,39 +174,10 @@ export default function SearchBar({ handleSearchBarToggle, }) {
|
|
|
127
174
|
suggestion: SuggestionTemplate,
|
|
128
175
|
empty: EmptyTemplate,
|
|
129
176
|
footer: ({ query, isEmpty }) => {
|
|
130
|
-
if (isEmpty) {
|
|
177
|
+
if (isEmpty && !searchContext) {
|
|
131
178
|
return;
|
|
132
179
|
}
|
|
133
|
-
const a =
|
|
134
|
-
const params = new URLSearchParams();
|
|
135
|
-
params.set("q", query);
|
|
136
|
-
if (Array.isArray(searchContextByPaths)) {
|
|
137
|
-
params.set("ctx", searchContext);
|
|
138
|
-
}
|
|
139
|
-
if (versionUrl !== baseUrl) {
|
|
140
|
-
if (!versionUrl.startsWith(baseUrl)) {
|
|
141
|
-
throw new Error(`Version url '${versionUrl}' does not start with base url '${baseUrl}', this is a bug of \`@easyops-cn/docusaurus-search-local\`, please report it.`);
|
|
142
|
-
}
|
|
143
|
-
params.set("version", versionUrl.substring(baseUrl.length));
|
|
144
|
-
}
|
|
145
|
-
const url = `${baseUrl}search?${params.toString()}`;
|
|
146
|
-
a.href = url;
|
|
147
|
-
a.textContent = searchContext
|
|
148
|
-
? translate({
|
|
149
|
-
id: "theme.SearchBar.searchInContext",
|
|
150
|
-
message: "See all results in {context}",
|
|
151
|
-
}, { context: searchContext })
|
|
152
|
-
: translate({
|
|
153
|
-
id: "theme.SearchBar.seeAll",
|
|
154
|
-
message: "See all results",
|
|
155
|
-
});
|
|
156
|
-
a.addEventListener("click", (e) => {
|
|
157
|
-
if (!e.ctrlKey && !e.metaKey) {
|
|
158
|
-
e.preventDefault();
|
|
159
|
-
search.current?.autocomplete.close();
|
|
160
|
-
history.push(url);
|
|
161
|
-
}
|
|
162
|
-
});
|
|
180
|
+
const a = searchFooterLinkElement({ query, isEmpty });
|
|
163
181
|
const div = document.createElement("div");
|
|
164
182
|
div.className = styles.hitFooter;
|
|
165
183
|
div.appendChild(a);
|
|
@@ -86,14 +86,15 @@ function SearchPageContent() {
|
|
|
86
86
|
<h1>{pageTitle}</h1>
|
|
87
87
|
|
|
88
88
|
<div className="row">
|
|
89
|
-
<div className={clsx("col",
|
|
89
|
+
<div className={clsx("col", {
|
|
90
|
+
[styles.searchQueryColumn]: Array.isArray(searchContextByPaths),
|
|
90
91
|
"col--9": Array.isArray(searchContextByPaths),
|
|
91
92
|
"col--12": !Array.isArray(searchContextByPaths),
|
|
92
93
|
})}>
|
|
93
94
|
<input type="search" name="q" className={styles.searchQueryInput} aria-label="Search" onChange={handleSearchInputChange} value={searchQuery} autoComplete="off" autoFocus/>
|
|
94
95
|
</div>
|
|
95
|
-
{Array.isArray(searchContextByPaths) ? (<div className={clsx("col", "col--3", "padding-left--none", styles.
|
|
96
|
-
<select name="search-context" className={styles.
|
|
96
|
+
{Array.isArray(searchContextByPaths) ? (<div className={clsx("col", "col--3", "padding-left--none", styles.searchContextColumn)}>
|
|
97
|
+
<select name="search-context" className={styles.searchContextInput} id="context-selector" value={searchContext} onChange={(e) => updateSearchContext(e.target.value)}>
|
|
97
98
|
<option value="">
|
|
98
99
|
{useAllContextsWithNoSearchContext
|
|
99
100
|
? translate({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
.
|
|
1
|
+
.searchContextInput,
|
|
2
2
|
.searchQueryInput {
|
|
3
3
|
border-radius: var(--ifm-global-radius);
|
|
4
4
|
border: var(--ifm-global-border-width) solid
|
|
@@ -30,3 +30,24 @@
|
|
|
30
30
|
font-style: italic;
|
|
31
31
|
margin: 0.5rem 0px 0px;
|
|
32
32
|
}
|
|
33
|
+
|
|
34
|
+
@media only screen and (max-width: 996px) {
|
|
35
|
+
.searchQueryColumn {
|
|
36
|
+
max-width: 60% !important;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.searchContextColumn {
|
|
40
|
+
max-width: 40% !important;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media screen and (max-width: 576px) {
|
|
45
|
+
.searchQueryColumn {
|
|
46
|
+
max-width: 100% !important;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.searchContextColumn {
|
|
50
|
+
max-width: 100% !important;
|
|
51
|
+
padding-left: var(--ifm-spacing-horizontal) !important;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -5,10 +5,15 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const cheerio_1 = tslib_1.__importDefault(require("cheerio"));
|
|
6
6
|
const parseDocument_1 = require("./parseDocument");
|
|
7
7
|
const parsePage_1 = require("./parsePage");
|
|
8
|
-
function parse(html, type, url) {
|
|
8
|
+
function parse(html, type, url, { ignoreCssSelectors }) {
|
|
9
9
|
const $ = cheerio_1.default.load(html);
|
|
10
10
|
// Remove copy buttons from code boxes
|
|
11
11
|
$('div[class^="mdxCodeBlock_"] button').remove();
|
|
12
|
+
if (ignoreCssSelectors) {
|
|
13
|
+
for (const ignoreSelector of ignoreCssSelectors) {
|
|
14
|
+
$(ignoreSelector).remove();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
12
17
|
if (type === "docs") {
|
|
13
18
|
// Remove version badges
|
|
14
19
|
$("span.badge")
|
|
@@ -18,7 +18,7 @@ function postBuildFactory(config, searchIndexFilename) {
|
|
|
18
18
|
(0, debug_1.debugInfo)("parsing documents");
|
|
19
19
|
for (const versionData of data) {
|
|
20
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);
|
|
21
|
+
const allDocuments = yield (0, scanDocuments_1.scanDocuments)(versionData.paths, config);
|
|
22
22
|
(0, debug_1.debugInfo)("building index");
|
|
23
23
|
const docsByDirMap = new Map();
|
|
24
24
|
const { searchContextByPaths, hideSearchBarWithNoSearchContext, useAllContextsWithNoSearchContext, } = config;
|
|
@@ -12,6 +12,7 @@ function processPluginOptions(options, { siteDir, siteConfig: { themeConfig }, }
|
|
|
12
12
|
ensureArray(config, "docsDir");
|
|
13
13
|
ensureArray(config, "blogDir");
|
|
14
14
|
ensureArray(config, "ignoreFiles");
|
|
15
|
+
ensureArray(config, "ignoreCssSelectors");
|
|
15
16
|
config.docsRouteBasePath = config.docsRouteBasePath.map((basePath) => basePath.replace(/^\//, ""));
|
|
16
17
|
config.blogRouteBasePath = config.blogRouteBasePath.map((basePath) => basePath.replace(/^\//, ""));
|
|
17
18
|
config.docsDir = config.docsDir.map((dir) => path_1.default.resolve(siteDir, dir));
|
|
@@ -12,7 +12,7 @@ let nextDocId = 0;
|
|
|
12
12
|
const getNextDocId = () => {
|
|
13
13
|
return (nextDocId += 1);
|
|
14
14
|
};
|
|
15
|
-
function scanDocuments(DocInfoWithFilePathList) {
|
|
15
|
+
function scanDocuments(DocInfoWithFilePathList, config) {
|
|
16
16
|
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
17
17
|
const titleDocuments = [];
|
|
18
18
|
const headingDocuments = [];
|
|
@@ -21,7 +21,7 @@ function scanDocuments(DocInfoWithFilePathList) {
|
|
|
21
21
|
yield Promise.all(DocInfoWithFilePathList.map(({ filePath, url, type }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
22
22
|
(0, debug_1.debugVerbose)(`parsing %s file %o of %o`, type, path_1.default.relative(process.cwd(), filePath), url);
|
|
23
23
|
const html = yield readFileAsync(filePath, { encoding: "utf8" });
|
|
24
|
-
const { pageTitle, sections, breadcrumb } = (0, parse_1.parse)(html, type, url);
|
|
24
|
+
const { pageTitle, sections, breadcrumb } = (0, parse_1.parse)(html, type, url, config);
|
|
25
25
|
const titleId = getNextDocId();
|
|
26
26
|
titleDocuments.push({
|
|
27
27
|
i: titleId,
|
|
@@ -22,6 +22,7 @@ const schema = utils_validation_1.Joi.object({
|
|
|
22
22
|
searchResultContextMaxLength: utils_validation_1.Joi.number().default(50),
|
|
23
23
|
explicitSearchResultPath: utils_validation_1.Joi.boolean().default(false),
|
|
24
24
|
ignoreFiles: isArrayOfStringsOrRegExpsOrStringOrRegExp.default([]),
|
|
25
|
+
ignoreCssSelectors: isStringOrArrayOfStrings.default([]),
|
|
25
26
|
searchBarShortcut: utils_validation_1.Joi.boolean().default(true),
|
|
26
27
|
searchBarShortcutHint: utils_validation_1.Joi.boolean().default(true),
|
|
27
28
|
searchBarPosition: utils_validation_1.Joi.string().default("auto"),
|
package/dist/types/index.d.ts
CHANGED
|
@@ -103,6 +103,12 @@ export interface PluginOptions {
|
|
|
103
103
|
* @default []
|
|
104
104
|
*/
|
|
105
105
|
ignoreFiles?: string | RegExp | (string | RegExp)[];
|
|
106
|
+
/**
|
|
107
|
+
* A list of css selectors to ignore when indexing each page.
|
|
108
|
+
*
|
|
109
|
+
* @default []
|
|
110
|
+
*/
|
|
111
|
+
ignoreCssSelectors?: string | string[];
|
|
106
112
|
/**
|
|
107
113
|
* Whether to enable keyboard shortcut to focus in search bar.
|
|
108
114
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easyops-cn/docusaurus-search-local",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
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",
|