Skip to content

Commit 17af0b3

Browse files
committed
mathjax in markdown
1 parent 2b83ef4 commit 17af0b3

File tree

6 files changed

+104
-4
lines changed

6 files changed

+104
-4
lines changed

components/dash-core-components/package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/dash-core-components/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"react-resize-detector": "^6.7.6",
6262
"react-select-fast-filter-options": "^0.2.3",
6363
"react-virtualized-select": "^3.1.3",
64+
"remark-math": "^3.0.1",
6465
"uniqid": "^5.4.0"
6566
},
6667
"devDependencies": {

components/dash-core-components/src/components/Markdown.react.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import {asyncDecorator} from '@plotly/dash-component-plugins';
12
import PropTypes from 'prop-types';
2-
import React, {Component, lazy, Suspense} from 'react';
3+
import React, {Component, Suspense} from 'react';
34
import markdown from '../utils/LazyLoader/markdown';
4-
5-
const RealDashMarkdown = lazy(markdown);
5+
import mathjax from '../utils/LazyLoader/mathjax';
66

77
// eslint-disable-next-line valid-jsdoc
88
/**
@@ -11,6 +11,14 @@ const RealDashMarkdown = lazy(markdown);
1111
* [react-markdown](https://rexxars.github.io/react-markdown/) under the hood.
1212
*/
1313
export default class DashMarkdown extends Component {
14+
constructor(props) {
15+
super(props);
16+
17+
if (props.mathjax) {
18+
DashMarkdown._loadMathjax = true;
19+
}
20+
}
21+
1422
render() {
1523
return (
1624
<Suspense fallback={null}>
@@ -32,6 +40,11 @@ DashMarkdown.propTypes = {
3240
*/
3341
className: PropTypes.string,
3442

43+
/**
44+
* If true, loads mathjax v3 (tex-svg) into the page and use it in the markdown
45+
*/
46+
mathjax: PropTypes.bool,
47+
3548
/**
3649
* A boolean to control raw HTML escaping.
3750
* Setting HTML from code is risky because it's easy to
@@ -91,10 +104,18 @@ DashMarkdown.propTypes = {
91104
};
92105

93106
DashMarkdown.defaultProps = {
107+
mathjax: false,
94108
dangerously_allow_html: false,
95109
highlight_config: {},
96110
dedent: true,
97111
};
98112

113+
const RealDashMarkdown = asyncDecorator(DashMarkdown, () =>
114+
Promise.all([
115+
markdown(),
116+
DashMarkdown._loadMathjax ? mathjax() : undefined,
117+
]).then(([md]) => md)
118+
);
119+
99120
export const propTypes = DashMarkdown.propTypes;
100121
export const defaultProps = DashMarkdown.defaultProps;

components/dash-core-components/src/fragments/Markdown.react.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React, {Component} from 'react';
22
import {mergeDeepRight, pick, type} from 'ramda';
33
import JsxParser from 'react-jsx-parser';
44
import Markdown from 'react-markdown';
5+
import RemarkMath from 'remark-math';
56

7+
import Math from './Math.react';
68
import MarkdownHighlighter from '../utils/MarkdownHighlighter';
79
import {propTypes, defaultProps} from '../components/Markdown.react';
810

@@ -85,6 +87,7 @@ export default class DashMarkdown extends Component {
8587
highlight_config,
8688
loading_state,
8789
dangerously_allow_html,
90+
mathjax,
8891
children,
8992
dedent,
9093
} = this.props;
@@ -131,7 +134,16 @@ export default class DashMarkdown extends Component {
131134
<Markdown
132135
source={displayText}
133136
escapeHtml={!dangerously_allow_html}
137+
plugins={mathjax ? [RemarkMath] : []}
134138
renderers={{
139+
math: props => (
140+
<Math tex={props.value} inline={false} />
141+
),
142+
143+
inlineMath: props => (
144+
<Math tex={props.value} inline={true} />
145+
),
146+
135147
html: props =>
136148
props.escapeHtml ? (
137149
props.value
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import PropTypes from 'prop-types';
2+
import React, {Component} from 'react';
3+
4+
export default class DashMath extends Component {
5+
constructor(props) {
6+
super(props);
7+
this.span_element = React.createRef();
8+
}
9+
10+
componentDidMount() {
11+
this.renderMath();
12+
}
13+
14+
componentDidUpdate(prevProps) {
15+
if (
16+
prevProps.tex !== this.props.tex ||
17+
prevProps.inline !== this.props.inline
18+
) {
19+
this.renderMath();
20+
}
21+
}
22+
23+
renderMath() {
24+
if (window.MathJax && window.MathJax.typeset) {
25+
window.MathJax.typeset([this.span_element.current]);
26+
}
27+
}
28+
29+
render() {
30+
return (
31+
<span ref={this.span_element}>
32+
{this.props.inline ? String.raw`\(` : String.raw`\[`}
33+
{this.props.tex}
34+
{this.props.inline ? String.raw`\)` : String.raw`\]`}
35+
</span>
36+
);
37+
}
38+
}
39+
40+
DashMath.propTypes = {
41+
tex: PropTypes.string,
42+
inline: PropTypes.bool,
43+
};
44+
45+
DashMath.defaultProps = {
46+
tex: '',
47+
inline: true,
48+
};
49+
50+
export const propTypes = DashMath.propTypes;
51+
export const defaultProps = DashMath.defaultProps;

components/dash-core-components/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ module.exports = (env, argv) => {
6565
},
6666
{
6767
test: /\.jsx?$/,
68-
include: /node_modules[\\\/](react-jsx-parser|highlight[.]js|react-markdown|is-plain-obj|color)[\\\/]/,
68+
include: /node_modules[\\\/](react-jsx-parser|highlight[.]js|react-markdown|remark-math|is-plain-obj|color)[\\\/]/,
6969
use: {
7070
loader: 'babel-loader',
7171
options: {

0 commit comments

Comments
 (0)