Skip to content

Commit

Permalink
feat: support for searching code blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
chenjiahan committed Feb 2, 2025
1 parent 263a7ef commit f22e338
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 6 deletions.
5 changes: 5 additions & 0 deletions e2e/fixtures/search-code-blocks/doc/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Hello world

```js
console.log('hello from code block');
```
16 changes: 16 additions & 0 deletions e2e/fixtures/search-code-blocks/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@rspress-fixture/rspress-search-code-blocks",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rspress build",
"dev": "rspress dev",
"preview": "rspress preview"
},
"dependencies": {
"rspress": "workspace:*"
},
"devDependencies": {
"@types/node": "^18.11.17"
}
}
9 changes: 9 additions & 0 deletions e2e/fixtures/search-code-blocks/rspress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as path from 'node:path';
import { defineConfig } from 'rspress/config';

export default defineConfig({
root: path.join(__dirname, 'doc'),
search: {
codeBlocks: true,
},
});
1 change: 1 addition & 0 deletions e2e/fixtures/search-code-blocks/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
31 changes: 31 additions & 0 deletions e2e/tests/search-code-blocks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from 'node:path';
import { expect, test } from '@playwright/test';
import { getPort, killProcess, runDevCommand } from '../utils/runCommands';
import { searchInPage } from '../utils/search';

const fixtureDir = path.resolve(__dirname, '../fixtures');

test.describe('search code blocks test', async () => {
let appPort;
let app;

test.beforeAll(async () => {
const appDir = path.join(fixtureDir, 'search-code-blocks');
appPort = await getPort();
app = await runDevCommand(appDir, appPort);
});

test.afterAll(async () => {
if (app) {
await killProcess(app);
}
});

test('search index should include content of code blocks', async ({
page,
}) => {
await page.goto(`http://localhost:${appPort}`);
const suggestItems = await searchInPage(page, 'hello from code block');
expect(suggestItems.length).toBe(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export async function extractPageData(
root: string,
routeService: RouteService,
highlighterLangs: Set<string>,
searchCodeBlocks: boolean,
): Promise<PageIndexInfo[]> {
const pageData = await Promise.all(
routeService
Expand Down Expand Up @@ -108,7 +109,7 @@ export async function extractPageData(
{
// Skip code blocks
selector: 'pre > code',
format: 'skip',
format: searchCodeBlocks ? 'inlineTag' : 'skip',
},
...['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].map(tag => ({
selector: tag,
Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/node/runtimeModule/siteData/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,24 @@ export async function siteDataVMPlugin(context: FactoryContext) {

const highlightLanguages: Set<string> = new Set();
const replaceRules = userConfig?.replaceRules || [];

const searchConfig = userConfig?.search || {};

// If the dev server restart when config file, we will reuse the siteData instead of extracting the siteData from source files again.
const domain =
userConfig?.search && userConfig?.search?.mode === 'remote'
? (userConfig?.search.domain ?? '')
: '';
searchConfig?.mode === 'remote' ? (searchConfig.domain ?? '') : '';

const searchCodeBlocks =
'codeBlocks' in searchConfig ? searchConfig.codeBlocks : false;

const pages = await extractPageData(
replaceRules,
alias,
domain,
userDocRoot,
routeService,
highlightLanguages,
searchCodeBlocks,
);
// modify page index by plugins
await pluginDriver.modifySearchIndexData(pages);
Expand Down
33 changes: 32 additions & 1 deletion packages/document/docs/en/api/config/config-basic.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,21 @@ export default defineConfig({

## search

- Type: `{ searchHooks: string; versioned: boolean; }`
- Type:

```ts
type SearchOptions = {
searchHooks?: string;
versioned?: boolean;
codeBlocks?: boolean;
};
```

### searchHooks

- Type: `string`
- Default: `undefined`

You can add search runtime hooks logic through the `searchHooks` parameter, for example:

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

### versioned

- Type: `boolean`
- Default: `false`

If you are using `multiVersion`, the `versioned` parameter allows you to create a separate search index for each version of your documentation.
When enabled, the search will only query the index corresponding to the currently selected version.

Expand All @@ -295,6 +309,23 @@ export default defineConfig({
});
```

### codeBlocks

- Type: `boolean`
- Default: `false`

If enabled, the search index will include code block content, which allows users to search code blocks.

```ts title="rspress.config.ts"
import { defineConfig } from 'rspress/config';

export default defineConfig({
search: {
codeBlocks: true,
},
});
```

## globalUIComponents

- Type: `(string | [string, object])[]`
Expand Down
33 changes: 32 additions & 1 deletion packages/document/docs/zh/api/config/config-basic.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,21 @@ export default defineConfig({

## search

- Type: `{ searchHooks: string; versioned: boolean; }`
- Type:

```ts
type SearchOptions = {
searchHooks?: string;
versioned?: boolean;
codeBlocks?: boolean;
};
```

### searchHooks

- Type: `string`
- Default: `undefined`

你可以通过 `searchHooks` 参数来增加搜索运行时钩子逻辑,比如:

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

### versioned

- Type: `boolean`
- Default: `false`

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

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

### codeBlocks

- Type: `boolean`
- Default: `false`

开启后,搜索的索引将包含代码块的内容,从而允许用户搜索代码块。

```ts title="rspress.config.ts"
import { defineConfig } from 'rspress/config';

export default defineConfig({
search: {
codeBlocks: true,
},
});
```

## globalUIComponents

- Type: `(string | object)[]`
Expand Down
3 changes: 3 additions & 0 deletions packages/document/rspress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export default defineConfig({
}),
],
},
search: {
codeBlocks: true,
},
route: {
cleanUrls: true,
exclude: ['**/fragments/**'],
Expand Down
5 changes: 5 additions & 0 deletions packages/shared/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,11 @@ export type LocalSearchOptions = SearchHooks & {
* Whether to generate separate search index for each version
*/
versioned?: boolean;
/**
* If enabled, the search index will include code block content, which allows users to search code blocks.
* @default false
*/
codeBlocks?: boolean;
};

export type RemoteSearchIndexInfo =
Expand Down
10 changes: 10 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f22e338

Please sign in to comment.