Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions packages/core/src/node/route/extractPageData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,35 @@ describe('getPageIndexInfoByRoute', async () => {
`);
});

it('should strip MDX syntax while keeping visible content', async () => {
const pageIndexInfo = await getPageIndexInfoByRoute(
createRoute('with-mdx-syntax.mdx', fixtureContentProcessingDir),
{
alias: {},
replaceRules: [],
root: fixtureContentProcessingDir,
searchCodeBlocks: true,
},
);

expect(pageIndexInfo.content).toBe(
[
'Visible component content.',
'Text before text after.',
[
'{',
' "name": "create_shopping_plan",',
' "description": "keep spacing"',
'}',
].join('\n'),
].join('\n\n'),
);
expect(pageIndexInfo.content).not.toContain('```json');
expect(pageIndexInfo.content).not.toContain('should not be indexed');
expect(pageIndexInfo.content).not.toContain('hiddenExpression');
expect(pageIndexInfo.content).not.toContain('anotherHiddenExpression');
});

it('should remove images from content', async () => {
const pageIndexInfo = await getPageIndexInfoByRoute(
createRoute('with-images.mdx', fixtureContentProcessingDir),
Expand Down
14 changes: 11 additions & 3 deletions packages/core/src/node/route/extractPageData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import { loadFrontMatter } from '@rspress/shared/node-utils';
import type { Node, Nodes, Root } from 'mdast';
import remarkGFM from 'remark-gfm';
import remarkMdx from 'remark-mdx';
import remarkParse from 'remark-parse';
import type { Plugin } from 'unified';
import { unified } from 'unified';
Expand Down Expand Up @@ -77,13 +78,16 @@ const remarkRemoveImages: Plugin<[], Root> = () => {
const createProcessor = (searchCodeBlocks: boolean) =>
unified()
.use(remarkParse)
.use(remarkMdx)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep .md pages on the Markdown parser

When a routed .md file contains raw HTML that is valid Markdown but invalid MDX/JSX—such as an HTML comment or <img> without a JSX self-closing slash—this unconditional plugin makes processor.parse(content) use MDX grammar and throw. The main compiler deliberately selects the format from the extension and enables rehypeRaw for .md in packages/core/src/node/mdx/options.ts, so these are supported pages; since createPageData awaits extraction without an error fallback, such a page can now abort a normal build. Apply remarkMdx only when processing .mdx files.

Useful? React with 👍 / 👎.

.use(remarkGFM)
.use(remarkRemoveImages)
.use(searchCodeBlocks ? [] : [remarkRemoveCodeBlocks]);

const processorWithCode = createProcessor(true);
const processorWithoutCode = createProcessor(false);

const MDX_TEXT_EXPRESSION_PLACEHOLDER = '\0';

/**
* Extract text content from a node recursively
*/
Expand All @@ -108,10 +112,7 @@ const SEARCH_SKIP_TYPES = new Set([
'footnoteReference',
'html',
'thematicBreak',
'mdxJsxFlowElement',
'mdxJsxTextElement',
'mdxFlowExpression',
'mdxTextExpression',
'mdxjsEsm',
]);

Expand All @@ -131,6 +132,11 @@ const SEARCH_BLOCK_TYPES = new Set([
function extractSearchText(node: Nodes, codeblocks: boolean): Array<string> {
const { type } = node;

// Keep a placeholder so only whitespace around removed inline expressions is normalized later.
if (type === 'mdxTextExpression') {
return [MDX_TEXT_EXPRESSION_PLACEHOLDER];
}

// Return an empty string for any kind of "non-content" node
if (SEARCH_SKIP_TYPES.has(type)) {
return [];
Expand Down Expand Up @@ -202,6 +208,8 @@ function buildSearchContent(
.join('')
// \t\n replace so we don't have trailing whitespace on table rows that aren't at the end of the text
.replaceAll('\t\n', '\n')
// Replace only removed inline MDX expressions and their surrounding spaces.
.replaceAll(/(?: *\0 *)+/g, ' ')
.trim();
if (!text) {
continue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Page with MDX syntax

export const hiddenExport = 'should not be indexed';

<Demo label="should not be indexed">
Visible component content.
{hiddenExpression}
</Demo>

Text before {anotherHiddenExpression} text after.

```json
{
"name": "create_shopping_plan",
"description": "keep spacing"
}
```
Loading