Skip to content

Commit 4711764

Browse files
committed
feat: add optional remarkIgnoreMarkdown plugin to avoid markdown transform to HTML
1 parent 78d5648 commit 4711764

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

src/components/Message/renderText/__tests__/renderText.test.js

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
imageToLink,
88
keepLineBreaksPlugin,
99
plusPlusToEmphasis,
10+
remarkIgnoreMarkdown,
1011
} from '../remarkPlugins';
1112
import { defaultAllowedTagNames, renderText } from '../renderText';
1213
import '@testing-library/jest-dom';
@@ -306,19 +307,19 @@ describe(`renderText`, () => {
306307
});
307308
});
308309

309-
describe('keepLineBreaksPlugin', () => {
310-
const lineBreaks = '\n\n\n';
311-
const paragraphText = `a${lineBreaks}b${lineBreaks}c`;
312-
const unorderedListText = `* item 1${lineBreaks}* item 2${lineBreaks}* item 3`;
313-
const orderedListText = `1. item 1${lineBreaks}2. item 2${lineBreaks}3. item 3`;
314-
const headingText = `## Heading${lineBreaks}a`;
315-
const codeBlockText = 'a\n\n\n```b```\n\n\nc';
316-
const horizontalRuleText = `a${lineBreaks}---${lineBreaks}b`;
317-
const blockquoteText = `a${lineBreaks}>b${lineBreaks}c`;
318-
const withStrikeThroughText = `a${lineBreaks}${strikeThroughText}${lineBreaks}b`;
319-
const tableText = `a${lineBreaks}| a | b | c | d |\n| - | :- | -: | :-: |\n| a | b | c | d |${lineBreaks}c`;
320-
const multilineWithStrongText = 'This is **the first** line\n\nThis is the second line';
310+
const lineBreaks = '\n\n\n';
311+
const paragraphText = `a${lineBreaks}b${lineBreaks}c`;
312+
const unorderedListText = `* item 1${lineBreaks}* item 2${lineBreaks}* item 3`;
313+
const orderedListText = `1. item 1${lineBreaks}2. item 2${lineBreaks}3. item 3`;
314+
const headingText = `## Heading${lineBreaks}a`;
315+
const codeBlockText = 'a\n\n\n```b```\n\n\nc';
316+
const horizontalRuleText = `a${lineBreaks}---${lineBreaks}b`;
317+
const blockquoteText = `a${lineBreaks}>b${lineBreaks}c`;
318+
const withStrikeThroughText = `a${lineBreaks}${strikeThroughText}${lineBreaks}b`;
319+
const tableText = `a${lineBreaks}| a | b | c | d |\n| - | :- | -: | :-: |\n| a | b | c | d |${lineBreaks}c`;
320+
const multilineWithStrongText = 'This is **the first** line\n\nThis is the second line';
321321

322+
describe('keepLineBreaksPlugin', () => {
322323
const doRenderText = (text, present) => {
323324
const Markdown = renderText(
324325
text,
@@ -500,3 +501,37 @@ describe('imageToLink', () => {
500501
).not.toBeInTheDocument();
501502
});
502503
});
504+
505+
describe('remarkIgnoreMarkdown', () => {
506+
const text = [
507+
headingText,
508+
paragraphText,
509+
unorderedListText,
510+
orderedListText,
511+
codeBlockText,
512+
horizontalRuleText,
513+
blockquoteText,
514+
withStrikeThroughText,
515+
tableText,
516+
multilineWithStrongText,
517+
].join('\n');
518+
519+
const renderWithPlugin = (plugins = []) => {
520+
const Markdown = renderText(
521+
text,
522+
{},
523+
{ getRemarkPlugins: () => [...plugins, remarkIgnoreMarkdown] },
524+
);
525+
return render(Markdown).container;
526+
};
527+
528+
it('skips the markdown transformation and keeps the original escaped text and lines', () => {
529+
expect(renderWithPlugin().innerHTML).toBe(`<p>${text.replace(/>/g, '&gt;')}</p>`);
530+
});
531+
532+
it('keeps line without keepLineBreaksPlugin', () => {
533+
expect(renderWithPlugin([keepLineBreaksPlugin]).innerHTML).toBe(
534+
renderWithPlugin().innerHTML,
535+
);
536+
});
537+
});

src/components/Message/renderText/remarkPlugins/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './htmlToTextPlugin';
22
export * from './imageToLink';
33
export * from './keepLineBreaksPlugin';
44
export * from './plusPlusToEmphasis';
5+
export * from './remarkIgnoreMarkdown';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Plugin } from 'unified';
2+
import type { Paragraph, Root, Text } from 'mdast';
3+
4+
/**
5+
* Replace the parsed Markdown tree with a single paragraph containing the
6+
* original source as a plain text node. No Markdown formatting is interpreted.
7+
* React will escape it.
8+
*/
9+
export const remarkIgnoreMarkdown: Plugin<[], Root> = () => (tree, file) => {
10+
const source = String(file.value ?? '');
11+
12+
const text: Text = { type: 'text', value: source };
13+
const paragraph: Paragraph = { children: [text], type: 'paragraph' };
14+
15+
tree.children = [paragraph];
16+
};

0 commit comments

Comments
 (0)