Skip to content

Commit dfcaf89

Browse files
authored
feat: support for searching code blocks (#1797)
1 parent 519f583 commit dfcaf89

File tree

12 files changed

+155
-6
lines changed

12 files changed

+155
-6
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Hello world
2+
3+
```js
4+
console.log('hello from code block');
5+
```
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "@rspress-fixture/rspress-search-code-blocks",
3+
"version": "1.0.0",
4+
"private": true,
5+
"scripts": {
6+
"build": "rspress build",
7+
"dev": "rspress dev",
8+
"preview": "rspress preview"
9+
},
10+
"dependencies": {
11+
"rspress": "workspace:*"
12+
},
13+
"devDependencies": {
14+
"@types/node": "^18.11.17"
15+
}
16+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import * as path from 'node:path';
2+
import { defineConfig } from 'rspress/config';
3+
4+
export default defineConfig({
5+
root: path.join(__dirname, 'doc'),
6+
search: {
7+
codeBlocks: true,
8+
},
9+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import path from 'node:path';
2+
import { expect, test } from '@playwright/test';
3+
import { getPort, killProcess, runDevCommand } from '../utils/runCommands';
4+
import { searchInPage } from '../utils/search';
5+
6+
const fixtureDir = path.resolve(__dirname, '../fixtures');
7+
8+
test.describe('search code blocks test', async () => {
9+
let appPort;
10+
let app;
11+
12+
test.beforeAll(async () => {
13+
const appDir = path.join(fixtureDir, 'search-code-blocks');
14+
appPort = await getPort();
15+
app = await runDevCommand(appDir, appPort);
16+
});
17+
18+
test.afterAll(async () => {
19+
if (app) {
20+
await killProcess(app);
21+
}
22+
});
23+
24+
test('search index should include content of code blocks', async ({
25+
page,
26+
}) => {
27+
await page.goto(`http://localhost:${appPort}`);
28+
const suggestItems = await searchInPage(page, 'hello from code block');
29+
expect(suggestItems.length).toBe(1);
30+
});
31+
});

packages/core/src/node/runtimeModule/siteData/extractPageData.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export async function extractPageData(
3636
root: string,
3737
routeService: RouteService,
3838
highlighterLangs: Set<string>,
39+
searchCodeBlocks: boolean,
3940
): Promise<PageIndexInfo[]> {
4041
const pageData = await Promise.all(
4142
routeService
@@ -108,7 +109,7 @@ export async function extractPageData(
108109
{
109110
// Skip code blocks
110111
selector: 'pre > code',
111-
format: 'skip',
112+
format: searchCodeBlocks ? 'block' : 'skip',
112113
},
113114
...['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].map(tag => ({
114115
selector: tag,

packages/core/src/node/runtimeModule/siteData/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,24 @@ export async function siteDataVMPlugin(context: FactoryContext) {
4141

4242
const highlightLanguages: Set<string> = new Set();
4343
const replaceRules = userConfig?.replaceRules || [];
44+
45+
const searchConfig = userConfig?.search || {};
46+
4447
// If the dev server restart when config file, we will reuse the siteData instead of extracting the siteData from source files again.
4548
const domain =
46-
userConfig?.search && userConfig?.search?.mode === 'remote'
47-
? (userConfig?.search.domain ?? '')
48-
: '';
49+
searchConfig?.mode === 'remote' ? (searchConfig.domain ?? '') : '';
50+
51+
const searchCodeBlocks =
52+
'codeBlocks' in searchConfig ? searchConfig.codeBlocks : false;
53+
4954
const pages = await extractPageData(
5055
replaceRules,
5156
alias,
5257
domain,
5358
userDocRoot,
5459
routeService,
5560
highlightLanguages,
61+
searchCodeBlocks,
5662
);
5763
// modify page index by plugins
5864
await pluginDriver.modifySearchIndexData(pages);

packages/document/docs/en/api/config/config-basic.mdx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,21 @@ export default defineConfig({
261261

262262
## search
263263

264-
- Type: `{ searchHooks: string; versioned: boolean; }`
264+
- Type:
265+
266+
```ts
267+
type SearchOptions = {
268+
searchHooks?: string;
269+
versioned?: boolean;
270+
codeBlocks?: boolean;
271+
};
272+
```
265273

266274
### searchHooks
267275

276+
- Type: `string`
277+
- Default: `undefined`
278+
268279
You can add search runtime hooks logic through the `searchHooks` parameter, for example:
269280

270281
```ts title="rspress.config.ts"
@@ -282,6 +293,9 @@ For specific hook logic, you can read [Customize Search Functions](/guide/advanc
282293

283294
### versioned
284295

296+
- Type: `boolean`
297+
- Default: `false`
298+
285299
If you are using `multiVersion`, the `versioned` parameter allows you to create a separate search index for each version of your documentation.
286300
When enabled, the search will only query the index corresponding to the currently selected version.
287301

@@ -295,6 +309,23 @@ export default defineConfig({
295309
});
296310
```
297311

312+
### codeBlocks
313+
314+
- Type: `boolean`
315+
- Default: `false`
316+
317+
If enabled, the search index will include code block content, which allows users to search code blocks.
318+
319+
```ts title="rspress.config.ts"
320+
import { defineConfig } from 'rspress/config';
321+
322+
export default defineConfig({
323+
search: {
324+
codeBlocks: true,
325+
},
326+
});
327+
```
328+
298329
## globalUIComponents
299330

300331
- Type: `(string | [string, object])[]`

packages/document/docs/zh/api/config/config-basic.mdx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,21 @@ export default defineConfig({
261261

262262
## search
263263

264-
- Type: `{ searchHooks: string; versioned: boolean; }`
264+
- Type:
265+
266+
```ts
267+
type SearchOptions = {
268+
searchHooks?: string;
269+
versioned?: boolean;
270+
codeBlocks?: boolean;
271+
};
272+
```
265273

266274
### searchHooks
267275

276+
- Type: `string`
277+
- Default: `undefined`
278+
268279
你可以通过 `searchHooks` 参数来增加搜索运行时钩子逻辑,比如:
269280

270281
```ts title="rspress.config.ts"
@@ -282,6 +293,9 @@ export default defineConfig({
282293

283294
### versioned
284295

296+
- Type: `boolean`
297+
- Default: `false`
298+
285299
如果你配置了 `multiVersion`,可以使用 `versioned` 参数为文档的每个版本创建单独的搜索索引。开启该选项后,搜索将仅会查询当前所选版本对应的索引。
286300

287301
```ts title="rspress.config.ts"
@@ -294,6 +308,23 @@ export default defineConfig({
294308
});
295309
```
296310

311+
### codeBlocks
312+
313+
- Type: `boolean`
314+
- Default: `false`
315+
316+
开启后,搜索的索引将包含代码块的内容,从而允许用户搜索代码块。
317+
318+
```ts title="rspress.config.ts"
319+
import { defineConfig } from 'rspress/config';
320+
321+
export default defineConfig({
322+
search: {
323+
codeBlocks: true,
324+
},
325+
});
326+
```
327+
297328
## globalUIComponents
298329

299330
- Type: `(string | object)[]`

packages/document/rspress.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export default defineConfig({
4545
}),
4646
],
4747
},
48+
search: {
49+
codeBlocks: true,
50+
},
4851
route: {
4952
cleanUrls: true,
5053
exclude: ['**/fragments/**'],

0 commit comments

Comments
 (0)