Skip to content

Commit 064ba2e

Browse files
authored
Merge pull request #5 from easyops-cn/steve/generate
Steve/generate
2 parents 3313552 + 90e5b1a commit 064ba2e

File tree

12 files changed

+310
-112
lines changed

12 files changed

+310
-112
lines changed

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# @easyops-cn/docusaurus-search-local
22

3+
![Npm Version](https://img.shields.io/npm/v/@easyops-cn/docusaurus-search-local)
34
[![Build Status](https://travis-ci.com/easyops-cn/docusaurus-search-local.svg?branch=master)](https://travis-ci.com/easyops-cn/docusaurus-search-local)
45
[![Coverage Status](https://coveralls.io/repos/github/easyops-cn/docusaurus-search-local/badge.svg?branch=master)](https://coveralls.io/github/easyops-cn/docusaurus-search-local?branch=master)
56

7+
An offline/local search plugin for [Docusaurus v2](https://v2.docusaurus.io/).
8+
69
> Original forked from [cmfcmf/docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local).
710
>
811
> Then later fully rewritten with TypeScript 💪, styles polished 💅, language of Chinese supported 🇨🇳, and tests covered ✅.
@@ -81,7 +84,7 @@ yarn add nodejieba
8184

8285
## Custom Styles
8386

84-
This plugin is shipped with polished styles just like the Algolia Search on the Docusaurus V2 website. Feel free to override these css custom properties (css variables) below.
87+
This plugin is shipped with polished styles just like the Algolia Search on the Docusaurus v2 website. Feel free to override these css custom properties (css variables) below.
8588

8689
| Var | Default (light) | Default (dark) |
8790
| -------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------- |

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
},
2222
"license": "MIT",
2323
"dependencies": {
24+
"@hapi/joi": "^17.1.1",
2425
"autocomplete.js": "^0.38.0",
2526
"cheerio": "^1.0.0-rc.3",
2627
"debug": "^4.2.0",
28+
"fs-extra": "^9.0.1",
2729
"klaw-sync": "^6.0.0",
2830
"lunr": "^2.3.9",
2931
"lunr-languages": "^1.4.0"
@@ -36,6 +38,8 @@
3638
"@types/debug": "^4.1.5",
3739
"@types/enzyme": "^3.10.7",
3840
"@types/enzyme-adapter-react-16": "^1.0.6",
41+
"@types/fs-extra": "^9.0.2",
42+
"@types/hapi__joi": "^17.1.6",
3943
"@types/jest": "^26.0.14",
4044
"@types/klaw-sync": "^6.0.0",
4145
"@types/lunr": "^2.3.3",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from "../../../generated.js";
1+
export * from "@generated/@easyops-cn/docusaurus-search-local/default/generated.js";

src/server/index.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import path from "path";
2-
2+
import fs from "fs-extra";
33
import { DocusaurusContext, PluginOptions } from "../shared/interfaces";
44
import { processPluginOptions } from "./utils/processPluginOptions";
55
import { postBuildFactory } from "./utils/postBuildFactory";
66
import { generate } from "./utils/generate";
77

8-
module.exports = function DocusaurusSearchLocalPlugin(
8+
const PLUGIN_NAME = "@easyops-cn/docusaurus-search-local";
9+
10+
export default function DocusaurusSearchLocalPlugin(
911
context: DocusaurusContext,
1012
options?: PluginOptions
1113
): any {
1214
const config = processPluginOptions(options, context.siteDir);
1315

14-
generate(config);
16+
const dir = path.join(context.generatedFilesDir, PLUGIN_NAME, "default");
17+
fs.ensureDirSync(dir);
18+
generate(config, dir);
1519

1620
return {
17-
name: "@easyops-cn/docusaurus-search-local",
21+
name: PLUGIN_NAME,
1822
getThemePath() {
1923
return path.resolve(__dirname, "../../client/client/theme");
2024
},
2125
postBuild: postBuildFactory(config),
2226
};
23-
};
27+
}
28+
29+
export { validateOptions } from "./utils/validateOptions";

src/server/utils/generate.spec.ts

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ const mockWriteFileSync = jest
1414
);
1515

1616
describe("generate", () => {
17-
test.each<[string[], string[]]>([
17+
test.each<[string[], any[]]>([
1818
[
1919
["en"],
2020
[
21-
'import lunr from "lunr";',
21+
expect.stringMatching(/^import lunr from ".+\/lunr\/lunr\.js";$/),
2222
'export const indexHash = "abc";',
2323
"export const searchResultLimits = 8;",
2424
"export const searchResultContextMaxLength = 50;",
@@ -27,9 +27,11 @@ describe("generate", () => {
2727
[
2828
["zh"],
2929
[
30-
'import lunr from "lunr";',
31-
'require("lunr-languages/lunr.stemmer.support")(lunr);',
32-
'require("./client/shared/lunrLanguageZh").lunrLanguageZh(lunr);',
30+
expect.stringMatching(/^import lunr from ".+\/lunr\/lunr\.js";$/),
31+
expect.stringMatching(
32+
/^require\(".+\/lunr-languages\/lunr\.stemmer\.support\.js"\)\(lunr\);$/
33+
),
34+
'require("@easyops-cn/docusaurus-search-local/dist/client/shared/lunrLanguageZh").lunrLanguageZh(lunr);',
3335
'export const indexHash = "abc";',
3436
"export const searchResultLimits = 8;",
3537
"export const searchResultContextMaxLength = 50;",
@@ -38,9 +40,13 @@ describe("generate", () => {
3840
[
3941
["es"],
4042
[
41-
'import lunr from "lunr";',
42-
'require("lunr-languages/lunr.stemmer.support")(lunr);',
43-
'require("lunr-languages/lunr.es")(lunr);',
43+
expect.stringMatching(/^import lunr from ".+\/lunr\/lunr\.js";$/),
44+
expect.stringMatching(
45+
/^require\(".+\/lunr-languages\/lunr\.stemmer\.support\.js"\)\(lunr\);$/
46+
),
47+
expect.stringMatching(
48+
/^require\(".+\/lunr-languages\/lunr\.es\.js"\)\(lunr\);$/
49+
),
4450
'export const indexHash = "abc";',
4551
"export const searchResultLimits = 8;",
4652
"export const searchResultContextMaxLength = 50;",
@@ -49,10 +55,14 @@ describe("generate", () => {
4955
[
5056
["en", "zh"],
5157
[
52-
'import lunr from "lunr";',
53-
'require("lunr-languages/lunr.stemmer.support")(lunr);',
54-
'require("./client/shared/lunrLanguageZh").lunrLanguageZh(lunr);',
55-
'require("lunr-languages/lunr.multi")(lunr);',
58+
expect.stringMatching(/^import lunr from ".+\/lunr\/lunr\.js";$/),
59+
expect.stringMatching(
60+
/^require\(".+\/lunr-languages\/lunr\.stemmer\.support\.js"\)\(lunr\);$/
61+
),
62+
'require("@easyops-cn/docusaurus-search-local/dist/client/shared/lunrLanguageZh").lunrLanguageZh(lunr);',
63+
expect.stringMatching(
64+
/^require\(".+\/lunr-languages\/lunr\.multi\.js"\)\(lunr\);$/
65+
),
5666
'export const indexHash = "abc";',
5767
"export const searchResultLimits = 8;",
5868
"export const searchResultContextMaxLength = 50;",
@@ -61,25 +71,38 @@ describe("generate", () => {
6171
[
6272
["en", "es", "zh"],
6373
[
64-
'import lunr from "lunr";',
65-
'require("lunr-languages/lunr.stemmer.support")(lunr);',
66-
'require("lunr-languages/lunr.es")(lunr);',
67-
'require("./client/shared/lunrLanguageZh").lunrLanguageZh(lunr);',
68-
'require("lunr-languages/lunr.multi")(lunr);',
74+
expect.stringMatching(/^import lunr from ".+\/lunr\/lunr\.js";$/),
75+
expect.stringMatching(
76+
/^require\(".+\/lunr-languages\/lunr\.stemmer\.support\.js"\)\(lunr\);$/
77+
),
78+
expect.stringMatching(
79+
/^require\(".+\/lunr-languages\/lunr\.es\.js"\)\(lunr\);$/
80+
),
81+
'require("@easyops-cn/docusaurus-search-local/dist/client/shared/lunrLanguageZh").lunrLanguageZh(lunr);',
82+
expect.stringMatching(
83+
/^require\(".+\/lunr-languages\/lunr\.multi\.js"\)\(lunr\);$/
84+
),
6985
'export const indexHash = "abc";',
7086
"export const searchResultLimits = 8;",
7187
"export const searchResultContextMaxLength = 50;",
7288
],
7389
],
74-
])("generate({ language: %j }) should work", (language, contents) => {
75-
generate({
76-
language,
77-
searchResultLimits: 8,
78-
searchResultContextMaxLength: 50,
79-
} as ProcessedPluginOptions);
90+
])("generate({ language: %j }, dir) should work", (language, contents) => {
91+
generate(
92+
{
93+
language,
94+
searchResultLimits: 8,
95+
searchResultContextMaxLength: 50,
96+
} as ProcessedPluginOptions,
97+
"/tmp"
98+
);
8099
expect(mockWriteFileSync).toBeCalledWith(
81-
expect.stringContaining("generated.js"),
82-
contents.join("\n")
100+
"/tmp/generated.js",
101+
expect.any(String)
102+
);
103+
const calledContents = (mockWriteFileSync.mock.calls[0][1] as string).split(
104+
"\n"
83105
);
106+
expect(calledContents).toEqual(contents);
84107
});
85108
});

src/server/utils/generate.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,39 @@ import path from "path";
33
import { ProcessedPluginOptions } from "../../shared/interfaces";
44
import { getIndexHash } from "./getIndexHash";
55

6-
export function generate(config: ProcessedPluginOptions): void {
6+
export function generate(config: ProcessedPluginOptions, dir: string): void {
77
const { language, searchResultLimits, searchResultContextMaxLength } = config;
88
const indexHash = getIndexHash(config);
9-
const contents: string[] = ['import lunr from "lunr";'];
9+
const contents: string[] = [
10+
`import lunr from ${JSON.stringify(require.resolve("lunr"))};`,
11+
];
1012
if (language.length > 1 || language.some((item) => item !== "en")) {
11-
contents.push('require("lunr-languages/lunr.stemmer.support")(lunr);');
13+
contents.push(
14+
`require(${JSON.stringify(
15+
require.resolve("lunr-languages/lunr.stemmer.support")
16+
)})(lunr);`
17+
);
1218
}
1319
for (const lang of language.filter(
1420
(item) => item !== "en" && item !== "zh"
1521
)) {
16-
contents.push(`require("lunr-languages/lunr.${lang}")(lunr);`);
22+
contents.push(
23+
`require(${JSON.stringify(
24+
require.resolve(`lunr-languages/lunr.${lang}`)
25+
)})(lunr);`
26+
);
1727
}
1828
if (language.includes("zh")) {
1929
contents.push(
20-
'require("./client/shared/lunrLanguageZh").lunrLanguageZh(lunr);'
30+
'require("@easyops-cn/docusaurus-search-local/dist/client/shared/lunrLanguageZh").lunrLanguageZh(lunr);'
2131
);
2232
}
2333
if (language.length > 1) {
24-
contents.push('require("lunr-languages/lunr.multi")(lunr);');
34+
contents.push(
35+
`require(${JSON.stringify(
36+
require.resolve("lunr-languages/lunr.multi")
37+
)})(lunr);`
38+
);
2539
}
2640
contents.push(`export const indexHash = ${JSON.stringify(indexHash)};`);
2741
contents.push(
@@ -31,8 +45,5 @@ export function generate(config: ProcessedPluginOptions): void {
3145
)};`
3246
);
3347

34-
fs.writeFileSync(
35-
path.resolve(__dirname, "../../../generated.js"),
36-
contents.join("\n")
37-
);
48+
fs.writeFileSync(path.join(dir, "generated.js"), contents.join("\n"));
3849
}

src/server/utils/processPluginOptions.spec.ts

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,29 @@ import { processPluginOptions } from "./processPluginOptions";
44
describe("processPluginOptions", () => {
55
const siteDir = "/tmp";
66

7-
test.each<[PluginOptions, ProcessedPluginOptions]>([
7+
test.each<[PluginOptions, Partial<ProcessedPluginOptions>]>([
88
[
9-
undefined,
109
{
11-
blogRouteBasePath: "blog",
12-
blogDir: "/tmp/blog",
13-
docsRouteBasePath: "docs",
14-
docsDir: "/tmp/docs",
15-
hashed: false,
16-
indexBlog: true,
17-
indexDocs: true,
18-
indexPages: false,
19-
language: ["en"],
20-
removeDefaultStopWordFilter: false,
21-
searchResultLimits: 8,
22-
searchResultContextMaxLength: 50,
10+
docsDir: "docs",
11+
blogDir: "blog",
12+
language: "en",
2313
},
24-
],
25-
[
26-
{ language: ["en", "zh"] },
2714
{
28-
blogRouteBasePath: "blog",
2915
blogDir: "/tmp/blog",
30-
docsRouteBasePath: "docs",
3116
docsDir: "/tmp/docs",
32-
hashed: false,
33-
indexBlog: true,
34-
indexDocs: true,
35-
indexPages: false,
36-
language: ["en", "zh"],
37-
removeDefaultStopWordFilter: false,
38-
searchResultLimits: 8,
39-
searchResultContextMaxLength: 50,
17+
language: ["en"],
4018
},
4119
],
4220
[
4321
{
44-
docsDir: "src/docs",
45-
blogDir: "src/blog",
46-
searchResultLimits: 5,
47-
searchResultContextMaxLength: 30,
22+
docsDir: "docs",
23+
blogDir: "blog",
24+
language: ["en", "zh"],
4825
},
4926
{
50-
blogRouteBasePath: "blog",
51-
blogDir: "/tmp/src/blog",
52-
docsRouteBasePath: "docs",
53-
docsDir: "/tmp/src/docs",
54-
hashed: false,
55-
indexBlog: true,
56-
indexDocs: true,
57-
indexPages: false,
58-
language: ["en"],
59-
removeDefaultStopWordFilter: false,
60-
searchResultLimits: 5,
61-
searchResultContextMaxLength: 30,
27+
blogDir: "/tmp/blog",
28+
docsDir: "/tmp/docs",
29+
language: ["en", "zh"],
6230
},
6331
],
6432
])("processPluginOptions(...) should work", (options, config) => {

src/server/utils/processPluginOptions.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,7 @@ export function processPluginOptions(
55
options: PluginOptions | undefined,
66
siteDir: string
77
): ProcessedPluginOptions {
8-
const config = Object.assign(
9-
{
10-
indexDocs: true,
11-
indexBlog: true,
12-
indexPages: false,
13-
docsRouteBasePath: "/docs",
14-
blogRouteBasePath: "/blog",
15-
language: "en",
16-
hashed: false,
17-
docsDir: "docs",
18-
blogDir: "blog",
19-
removeDefaultStopWordFilter: false,
20-
searchResultLimits: 8,
21-
searchResultContextMaxLength: 50,
22-
},
23-
options
24-
) as ProcessedPluginOptions;
25-
config.docsRouteBasePath = (config.docsRouteBasePath as string).replace(
26-
/^\//,
27-
""
28-
);
29-
config.blogRouteBasePath = (config.blogRouteBasePath as string).replace(
30-
/^\//,
31-
""
32-
);
8+
const config = { ...options } as ProcessedPluginOptions;
339
config.docsDir = path.resolve(siteDir, config.docsDir);
3410
config.blogDir = path.resolve(siteDir, config.blogDir);
3511
if (!Array.isArray(config.language)) {

0 commit comments

Comments
 (0)