[MM-57710] Convert katex class component to function component (#26967)
* Convert katex class component to function component * Change formatting * Move props to one line each * Fix latex tests - shallow() does not work with useEffect() * Update snapshot for src/utils/message_html_to_component.test.tsx * Remove act() block * Expect that length of components with matching data-testid should be 1 * Revert behaviour of katex with error to render the error
Этот коммит содержится в:
@@ -2,18 +2,23 @@
|
|||||||
|
|
||||||
exports[`components/LatexBlock error in katex 1`] = `
|
exports[`components/LatexBlock error in katex 1`] = `
|
||||||
<div
|
<div
|
||||||
className="post-body--code tex"
|
class="post-body--code tex"
|
||||||
dangerouslySetInnerHTML={
|
data-testid="latex-enabled"
|
||||||
Object {
|
>
|
||||||
"__html": "<span class=\\"katex-error\\" title=\\"ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …i\\\\pi + 1 = 0\`\`\`\\" style=\\"color:#cc0000\\">\`\`\`latex e^{i\\\\pi + 1 = 0\`\`\`</span>",
|
<span
|
||||||
}
|
class="katex-error"
|
||||||
}
|
style="color:#cc0000"
|
||||||
/>
|
title="ParseError: KaTeX parse error: Expected '}', got 'EOF' at end of input: …i\\\\pi + 1 = 0\`\`\`"
|
||||||
|
>
|
||||||
|
\`\`\`latex e^{i\\pi + 1 = 0\`\`\`
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`components/LatexBlock latex is disabled 1`] = `
|
exports[`components/LatexBlock latex is disabled 1`] = `
|
||||||
<div
|
<div
|
||||||
className="post-body--code tex"
|
class="post-body--code tex"
|
||||||
|
data-testid="latex-disabled"
|
||||||
>
|
>
|
||||||
\`\`\`latex e^{i\\pi} + 1 = 0\`\`\`
|
\`\`\`latex e^{i\\pi} + 1 = 0\`\`\`
|
||||||
</div>
|
</div>
|
||||||
@@ -21,11 +26,248 @@ exports[`components/LatexBlock latex is disabled 1`] = `
|
|||||||
|
|
||||||
exports[`components/LatexBlock should match snapshot 1`] = `
|
exports[`components/LatexBlock should match snapshot 1`] = `
|
||||||
<div
|
<div
|
||||||
className="post-body--code tex"
|
class="post-body--code tex"
|
||||||
dangerouslySetInnerHTML={
|
data-testid="latex-enabled"
|
||||||
Object {
|
>
|
||||||
"__html": "<span class=\\"katex-display fleqn\\"><span class=\\"katex\\"><span class=\\"katex-mathml\\"><math xmlns=\\"http://www.w3.org/1998/Math/MathML\\" display=\\"block\\"><semantics><mrow><mi mathvariant=\\"normal\\">‘</mi><mi mathvariant=\\"normal\\">‘</mi><mi mathvariant=\\"normal\\">‘</mi><mi>l</mi><mi>a</mi><mi>t</mi><mi>e</mi><mi>x</mi><msup><mi>e</mi><mrow><mi>i</mi><mi>π</mi></mrow></msup><mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn><mi mathvariant=\\"normal\\">‘</mi><mi mathvariant=\\"normal\\">‘</mi><mi mathvariant=\\"normal\\">‘</mi></mrow><annotation encoding=\\"application/x-tex\\">\`\`\`latex e^{i\\\\pi} + 1 = 0\`\`\`</annotation></semantics></math></span><span class=\\"katex-html\\" aria-hidden=\\"true\\"><span class=\\"base\\"><span class=\\"strut\\" style=\\"height:0.958em;vertical-align:-0.0833em;\\"></span><span class=\\"mord\\">‘‘‘</span><span class=\\"mord mathnormal\\" style=\\"margin-right:0.01968em;\\">l</span><span class=\\"mord mathnormal\\">a</span><span class=\\"mord mathnormal\\">t</span><span class=\\"mord mathnormal\\">e</span><span class=\\"mord mathnormal\\">x</span><span class=\\"mord\\"><span class=\\"mord mathnormal\\">e</span><span class=\\"msupsub\\"><span class=\\"vlist-t\\"><span class=\\"vlist-r\\"><span class=\\"vlist\\" style=\\"height:0.8747em;\\"><span style=\\"top:-3.113em;margin-right:0.05em;\\"><span class=\\"pstrut\\" style=\\"height:2.7em;\\"></span><span class=\\"sizing reset-size6 size3 mtight\\"><span class=\\"mord mtight\\"><span class=\\"mord mathnormal mtight\\" style=\\"margin-right:0.03588em;\\">iπ</span></span></span></span></span></span></span></span></span><span class=\\"mspace\\" style=\\"margin-right:0.2222em;\\"></span><span class=\\"mbin\\">+</span><span class=\\"mspace\\" style=\\"margin-right:0.2222em;\\"></span></span><span class=\\"base\\"><span class=\\"strut\\" style=\\"height:0.6444em;\\"></span><span class=\\"mord\\">1</span><span class=\\"mspace\\" style=\\"margin-right:0.2778em;\\"></span><span class=\\"mrel\\">=</span><span class=\\"mspace\\" style=\\"margin-right:0.2778em;\\"></span></span><span class=\\"base\\"><span class=\\"strut\\" style=\\"height:0.6944em;\\"></span><span class=\\"mord\\">0‘‘‘</span></span></span></span></span>",
|
<span
|
||||||
}
|
class="katex-display fleqn"
|
||||||
}
|
>
|
||||||
/>
|
<span
|
||||||
|
class="katex"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="katex-mathml"
|
||||||
|
>
|
||||||
|
<math
|
||||||
|
display="block"
|
||||||
|
xmlns="http://www.w3.org/1998/Math/MathML"
|
||||||
|
>
|
||||||
|
<semantics>
|
||||||
|
<mrow>
|
||||||
|
<mi
|
||||||
|
mathvariant="normal"
|
||||||
|
>
|
||||||
|
‘
|
||||||
|
</mi>
|
||||||
|
<mi
|
||||||
|
mathvariant="normal"
|
||||||
|
>
|
||||||
|
‘
|
||||||
|
</mi>
|
||||||
|
<mi
|
||||||
|
mathvariant="normal"
|
||||||
|
>
|
||||||
|
‘
|
||||||
|
</mi>
|
||||||
|
<mi>
|
||||||
|
l
|
||||||
|
</mi>
|
||||||
|
<mi>
|
||||||
|
a
|
||||||
|
</mi>
|
||||||
|
<mi>
|
||||||
|
t
|
||||||
|
</mi>
|
||||||
|
<mi>
|
||||||
|
e
|
||||||
|
</mi>
|
||||||
|
<mi>
|
||||||
|
x
|
||||||
|
</mi>
|
||||||
|
<msup>
|
||||||
|
<mi>
|
||||||
|
e
|
||||||
|
</mi>
|
||||||
|
<mrow>
|
||||||
|
<mi>
|
||||||
|
i
|
||||||
|
</mi>
|
||||||
|
<mi>
|
||||||
|
π
|
||||||
|
</mi>
|
||||||
|
</mrow>
|
||||||
|
</msup>
|
||||||
|
<mo>
|
||||||
|
+
|
||||||
|
</mo>
|
||||||
|
<mn>
|
||||||
|
1
|
||||||
|
</mn>
|
||||||
|
<mo>
|
||||||
|
=
|
||||||
|
</mo>
|
||||||
|
<mn>
|
||||||
|
0
|
||||||
|
</mn>
|
||||||
|
<mi
|
||||||
|
mathvariant="normal"
|
||||||
|
>
|
||||||
|
‘
|
||||||
|
</mi>
|
||||||
|
<mi
|
||||||
|
mathvariant="normal"
|
||||||
|
>
|
||||||
|
‘
|
||||||
|
</mi>
|
||||||
|
<mi
|
||||||
|
mathvariant="normal"
|
||||||
|
>
|
||||||
|
‘
|
||||||
|
</mi>
|
||||||
|
</mrow>
|
||||||
|
<annotation
|
||||||
|
encoding="application/x-tex"
|
||||||
|
>
|
||||||
|
\`\`\`latex e^{i\\pi} + 1 = 0\`\`\`
|
||||||
|
</annotation>
|
||||||
|
</semantics>
|
||||||
|
</math>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
class="katex-html"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="base"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="strut"
|
||||||
|
style="height:0.958em;vertical-align:-0.0833em;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="mord"
|
||||||
|
>
|
||||||
|
‘‘‘
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal"
|
||||||
|
style="margin-right:0.01968em;"
|
||||||
|
>
|
||||||
|
l
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal"
|
||||||
|
>
|
||||||
|
a
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal"
|
||||||
|
>
|
||||||
|
t
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal"
|
||||||
|
>
|
||||||
|
e
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal"
|
||||||
|
>
|
||||||
|
x
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mord"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal"
|
||||||
|
>
|
||||||
|
e
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="msupsub"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="vlist-t"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="vlist-r"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="vlist"
|
||||||
|
style="height:0.8747em;"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style="top:-3.113em;margin-right:0.05em;"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="pstrut"
|
||||||
|
style="height:2.7em;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="sizing reset-size6 size3 mtight"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mord mtight"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mord mathnormal mtight"
|
||||||
|
style="margin-right:0.03588em;"
|
||||||
|
>
|
||||||
|
iπ
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mspace"
|
||||||
|
style="margin-right:0.2222em;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="mbin"
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mspace"
|
||||||
|
style="margin-right:0.2222em;"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="base"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="strut"
|
||||||
|
style="height:0.6444em;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="mord"
|
||||||
|
>
|
||||||
|
1
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mspace"
|
||||||
|
style="margin-right:0.2778em;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="mrel"
|
||||||
|
>
|
||||||
|
=
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="mspace"
|
||||||
|
style="margin-right:0.2778em;"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="base"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="strut"
|
||||||
|
style="height:0.6944em;"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="mord"
|
||||||
|
>
|
||||||
|
0‘‘‘
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import {shallow} from 'enzyme';
|
import {render, screen} from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import LatexBlock from 'components/latex_block/latex_block';
|
import LatexBlock from 'components/latex_block/latex_block';
|
||||||
|
|
||||||
|
import {withIntl} from 'tests/helpers/intl-test-helper';
|
||||||
|
|
||||||
describe('components/LatexBlock', () => {
|
describe('components/LatexBlock', () => {
|
||||||
const defaultProps = {
|
const defaultProps = {
|
||||||
content: '```latex e^{i\\pi} + 1 = 0```',
|
content: '```latex e^{i\\pi} + 1 = 0```',
|
||||||
@@ -13,9 +15,10 @@ describe('components/LatexBlock', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
test('should match snapshot', async () => {
|
test('should match snapshot', async () => {
|
||||||
const wrapper = shallow(<LatexBlock {...defaultProps}/>);
|
render(<LatexBlock {...defaultProps}/>);
|
||||||
await import('katex'); //manually import katex
|
const wrapper = await screen.findAllByTestId('latex-enabled');
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.at(0)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('latex is disabled', async () => {
|
test('latex is disabled', async () => {
|
||||||
@@ -24,9 +27,10 @@ describe('components/LatexBlock', () => {
|
|||||||
enableLatex: false,
|
enableLatex: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = shallow(<LatexBlock {...props}/>);
|
render(<LatexBlock {...props}/>);
|
||||||
await import('katex'); //manually import katex
|
const wrapper = await screen.findAllByTestId('latex-disabled');
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.at(0)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('error in katex', async () => {
|
test('error in katex', async () => {
|
||||||
@@ -35,8 +39,9 @@ describe('components/LatexBlock', () => {
|
|||||||
enableLatex: true,
|
enableLatex: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = shallow(<LatexBlock {...props}/>);
|
render(withIntl(<LatexBlock {...props}/>));
|
||||||
await import('katex'); //manually import katex
|
const wrapper = await screen.findAllByTestId('latex-enabled');
|
||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper.length).toBe(1);
|
||||||
|
expect(wrapper.at(0)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,74 +2,71 @@
|
|||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import type {KatexOptions} from 'katex';
|
import type {KatexOptions} from 'katex';
|
||||||
import React from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
type Katex = typeof import('katex');
|
type Katex = typeof import('katex');
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
content: string;
|
content: string;
|
||||||
enableLatex: boolean;
|
enableLatex?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
const LatexBlock = ({
|
||||||
katex?: Katex;
|
content,
|
||||||
}
|
enableLatex,
|
||||||
|
}: Props) => {
|
||||||
|
const [katex, setKatex] = useState<Katex | undefined>();
|
||||||
|
|
||||||
export default class LatexBlock extends React.PureComponent<Props, State> {
|
useEffect(() => {
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
katex: undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
|
||||||
import('katex').then((katex) => {
|
import('katex').then((katex) => {
|
||||||
this.setState({katex: katex.default});
|
setKatex(katex.default);
|
||||||
});
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!enableLatex || katex === undefined) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className='post-body--code tex'
|
||||||
|
data-testid='latex-disabled'
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.ReactNode {
|
try {
|
||||||
if (!this.props.enableLatex || this.state.katex === undefined) {
|
const katexOptions: KatexOptions = {
|
||||||
return (
|
throwOnError: false,
|
||||||
<div
|
displayMode: true,
|
||||||
className='post-body--code tex'
|
maxSize: 200,
|
||||||
>
|
maxExpand: 100,
|
||||||
{this.props.content}
|
fleqn: true,
|
||||||
</div>
|
};
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
const html = katex.renderToString(content, katexOptions);
|
||||||
const katexOptions: KatexOptions = {
|
|
||||||
throwOnError: false,
|
|
||||||
displayMode: true,
|
|
||||||
maxSize: 200,
|
|
||||||
maxExpand: 100,
|
|
||||||
fleqn: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const html = this.state.katex.renderToString(this.props.content, katexOptions);
|
return (
|
||||||
|
<div
|
||||||
return (
|
className='post-body--code tex'
|
||||||
<div
|
dangerouslySetInnerHTML={{__html: html}}
|
||||||
className='post-body--code tex'
|
data-testid='latex-enabled'
|
||||||
dangerouslySetInnerHTML={{__html: html}}
|
/>
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// This is never run because throwOnError is false
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className='post-body--code tex'
|
||||||
|
data-testid='latex-error'
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='katex.error'
|
||||||
|
defaultMessage={'Couldn\'t compile your Latex code. Please review the syntax and try again.'}
|
||||||
/>
|
/>
|
||||||
);
|
</div>
|
||||||
} catch (e) {
|
);
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className='post-body--code tex'
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id='katex.error'
|
|
||||||
defaultMessage="Couldn't compile your Latex code. Please review the syntax and try again."
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default React.memo(LatexBlock);
|
||||||
|
|||||||
@@ -129,10 +129,10 @@ Array [
|
|||||||
</p>,
|
</p>,
|
||||||
"
|
"
|
||||||
",
|
",
|
||||||
<Memo(Connect(LatexBlock))
|
<Memo(Connect(Component))
|
||||||
content="x^2 + y^2 = z^2"
|
content="x^2 + y^2 = z^2"
|
||||||
/>,
|
/>,
|
||||||
<Memo(Connect(LatexBlock))
|
<Memo(Connect(Component))
|
||||||
content="F_m - 2 = F_0 F_1 \\\\dots F_{m-1}"
|
content="F_m - 2 = F_0 F_1 \\\\dots F_{m-1}"
|
||||||
/>,
|
/>,
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user