Skip to content
Merged
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
27 changes: 27 additions & 0 deletions packages/react/__tests__/components.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import LaTeX2HTML5 from 'latex2js';
import nicebox from '../src/components/nicebox';
import enumerate from '../src/components/enumerate';
import math from '../src/components/math';
import { LaTeX } from '../src';

describe('nicebox', () => {
it('renders the parser-provided lines, not children', () => {
Expand Down Expand Up @@ -82,3 +83,29 @@ In DFS, $\omega_0 = 2\pi/p$.
expect(html).toContain('In DFS');
});
});

describe('LaTeX', () => {
it('reuses the parsed document when content is unchanged', () => {
const source = String.raw`\begin{nicebox}content\end{nicebox}`;
const instance = new LaTeX({ content: source });
(instance as any).state = { mathJaxLoaded: true };
const parse = jest.spyOn(LaTeX2HTML5.prototype, 'parse');

instance.render();
instance.render();

expect(parse).toHaveBeenCalledTimes(1);
parse.mockRestore();
});

it('typesets after an update when MathJax is loaded', () => {
const instance = new LaTeX({ content: 'content' });
(instance as any).state = { mathJaxLoaded: true };
const typesetMath = jest.spyOn(instance, 'typesetMath').mockImplementation(() => {});

instance.componentDidUpdate();

expect(typesetMath).toHaveBeenCalledTimes(1);
typesetMath.mockRestore();
});
});
43 changes: 23 additions & 20 deletions packages/react/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ interface LaTeXState {

export class LaTeX extends Component<LaTeXProps, LaTeXState> {
private containerRef = React.createRef<HTMLDivElement>();
private parsedContent: string | null = null;
private parsed: any = null;
private children: React.ReactElement[] = [];

constructor(props: LaTeXProps) {
super(props);
Expand All @@ -38,14 +41,12 @@ export class LaTeX extends Component<LaTeXProps, LaTeXState> {

componentDidMount() {
loadMathJax(() => {
this.setState({ mathJaxLoaded: true }, () => {
this.typesetMath();
});
this.setState({ mathJaxLoaded: true });
});
}

componentDidUpdate(prevProps: LaTeXProps) {
if (prevProps.content !== this.props.content && this.state.mathJaxLoaded) {
componentDidUpdate() {
if (this.state.mathJaxLoaded) {
this.typesetMath();
}
}
Expand All @@ -64,20 +65,22 @@ export class LaTeX extends Component<LaTeXProps, LaTeXState> {
return <div className="latex-container">Loading...</div>;
}

const latex = new LaTeX2HTML5();
const parsed = latex.parse(this.props.content);

const children: React.ReactElement[] = [];

parsed &&
parsed.forEach &&
parsed.forEach((el: any) => {
if (ELEMENTS.hasOwnProperty(el.type)) {
const elementType = el.type as keyof typeof ELEMENTS;
const Component = ELEMENTS[elementType];
children.push(createElement(Component as any, { ...el, key: children.length }));
}
});
if (this.parsedContent !== this.props.content) {
const latex = new LaTeX2HTML5();
this.parsed = latex.parse(this.props.content);
this.parsedContent = this.props.content;

this.children = [];
this.parsed &&
this.parsed.forEach &&
this.parsed.forEach((el: any) => {
if (ELEMENTS.hasOwnProperty(el.type)) {
const elementType = el.type as keyof typeof ELEMENTS;
const Component = ELEMENTS[elementType];
this.children.push(createElement(Component as any, { ...el, key: this.children.length }));
}
});
}

return (
<div className="latex-container" ref={this.containerRef}>
Expand All @@ -86,7 +89,7 @@ export class LaTeX extends Component<LaTeXProps, LaTeXState> {
package defines them before any math that uses them — the same
hidden-div approach the html5 and vue renderers use. */}
<div className="latex-macros" style={{ display: 'none' }}>{macroStr}</div>
{children}
{this.children}
</div>
);
}
Expand Down
Loading