feat: 增加Markdown组件用于渲染markdown格式的字符串

release/desktop
moonrailgun 3 years ago
parent e449bf9dac
commit 9328c9b8de

File diff suppressed because it is too large Load Diff

@ -42,6 +42,7 @@
"react-dom": "17.0.2",
"react-easy-crop": "^3.5.2",
"react-helmet": "^6.1.0",
"react-markdown": "6",
"react-mentions": "^4.3.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",

@ -0,0 +1,30 @@
import React, { useCallback } from 'react';
import { isValidStr } from 'tailchat-shared';
const ReactMarkdown = React.lazy(() => import('react-markdown'));
export const Markdown: React.FC<{
raw: string;
baseUrl?: string;
}> = React.memo(({ raw, baseUrl }) => {
const transformUrl = useCallback(
(url: string) => {
if (!isValidStr(baseUrl)) {
return url;
}
return new URL(url, baseUrl).href;
},
[baseUrl]
);
return (
<ReactMarkdown
transformImageUri={(src) => transformUrl(src)}
transformLinkUri={(href) => transformUrl(href)}
>
{raw}
</ReactMarkdown>
);
});
Markdown.displayName = 'Markdown';

@ -0,0 +1,49 @@
import React from 'react';
import { renderLazy } from '@test/utils/lazy';
import { Markdown } from '../Markdown';
describe('Markdown', () => {
test('heading', async () => {
const text = `
# Heading1
## Heading2
### Heading3
#### Heading4
##### Heading5
`;
const wrapper = await renderLazy(<Markdown raw={text} />);
expect(wrapper.container).toMatchSnapshot();
});
test('list', async () => {
const text = `
- 1
- 2
- 3
- 4
- 5
- 6
`;
const wrapper = await renderLazy(<Markdown raw={text} />);
expect(wrapper.container).toMatchSnapshot();
});
describe('link', () => {
const text = `
[https://tailchat.msgbyte.com/](https://tailchat.msgbyte.com/)
[./README.md](./README.md)
![](./demo.jpg)`;
test('without baseUrl', async () => {
const wrapper = await renderLazy(<Markdown raw={text} />);
expect(wrapper.container).toMatchSnapshot();
});
test('with baseUrl', async () => {
const wrapper = await renderLazy(
<Markdown raw={text} baseUrl="https://tailchat.msgbyte.com/" />
);
expect(wrapper.container).toMatchSnapshot();
});
});
});

@ -0,0 +1,134 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Markdown heading 1`] = `
<div>
<h1>
Heading1
</h1>
<h2>
Heading2
</h2>
<h3>
Heading3
</h3>
<h4>
Heading4
</h4>
<h5>
Heading5
</h5>
</div>
`;
exports[`Markdown link with baseUrl 1`] = `
<div>
<p>
<a
href="https://tailchat.msgbyte.com/"
>
https://tailchat.msgbyte.com/
</a>
<a
href="https://tailchat.msgbyte.com/README.md"
>
./README.md
</a>
<img
alt=""
src="https://tailchat.msgbyte.com/demo.jpg"
/>
</p>
</div>
`;
exports[`Markdown link without baseUrl 1`] = `
<div>
<p>
<a
href="https://tailchat.msgbyte.com/"
>
https://tailchat.msgbyte.com/
</a>
<a
href="./README.md"
>
./README.md
</a>
<img
alt=""
src="./demo.jpg"
/>
</p>
</div>
`;
exports[`Markdown list 1`] = `
<div>
<ul>
<li>
1
</li>
<li>
2
</li>
<li>
3
<ul>
<li>
4
</li>
<li>
5
<ul>
<li>
6
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
`;

@ -0,0 +1,24 @@
import { render } from '@testing-library/react';
import React, { Suspense } from 'react';
import { sleep } from 'tailchat-shared';
/**
* Suspense
*/
export function renderWithSuspense(ui: React.ReactElement) {
return render(ui, {
wrapper: (props) => (
<Suspense fallback="JestLoading">{props.children}</Suspense>
),
});
}
/**
*
*/
export async function renderLazy(ui: React.ReactElement, ms = 400) {
const wrapper = renderWithSuspense(ui);
await sleep(ms);
return wrapper;
}

@ -4,6 +4,7 @@
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@test/*": ["./test/*"],
"@assets/*": ["./assets/*"]
}
},

Loading…
Cancel
Save