Skip to content

Commit 4ba005f

Browse files
committed
Anton Akhmerov's workaround to mock v2 API for pages with both chtml & svg outputs
1 parent 1dd51fd commit 4ba005f

File tree

5 files changed

+174
-3
lines changed

5 files changed

+174
-3
lines changed

devtools/test_dashboard/index-mathjax3.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<title>Plotly.js Devtools</title>
4+
<title>Plotly.js Devtools - MathJax v3 loaded with svg output</title>
55
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:600,400,300,200|Droid+Sans|PT+Sans+Narrow|Gravitas+One|Droid+Sans+Mono|Droid+Serif|Raleway|Old+Standard+TT"/>
66
<link rel="stylesheet" type="text/css" href="./style.css">
77
</head>
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>Plotly.js Devtools - MathJax v3 loaded with chtml output</title>
5+
<p>MathJax $V^3$ with $chtml$ output on the page and <b>svg</b> output on the plotly graphs</p>
6+
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:600,400,300,200|Droid+Sans|PT+Sans+Narrow|Gravitas+One|Droid+Sans+Mono|Droid+Serif|Raleway|Old+Standard+TT"/>
7+
<link rel="stylesheet" type="text/css" href="./style.css">
8+
</head>
9+
<body>
10+
<header>
11+
<img src="http://images.plot.ly/logo/[email protected]" onClick="Tabs.reload();" />
12+
<span id="reload-time"></span>
13+
14+
<input id="mocks-search" type="text" placeholder="mocks search" />
15+
<input id="css-transform" type="text" placeholder="css transform" />
16+
</header>
17+
18+
<section id="mocks-list"></section>
19+
<div id="plots">
20+
<div id="graph"></div>
21+
</div>
22+
<div id="snapshot"></div>
23+
24+
<script>
25+
window.MathJax = window.MathJax || {
26+
// mocking v2 API as suggested by https://github.com/akhmerov namely to handle both chtml output on the page as well as svg outputs for plotly
27+
28+
startup: {
29+
//
30+
// Mapping of old extension names to new ones
31+
//
32+
requireMap: {
33+
AMSmath: 'ams',
34+
AMSsymbols: 'ams',
35+
AMScd: 'amscd',
36+
SVG: 'svg',
37+
noErrors: 'noerrors',
38+
noUndefined: 'noundefined'
39+
},
40+
ready() {
41+
// Here and later using recipe from https://github.com/mathjax/MathJax/issues/2705
42+
//
43+
// Get the MathJax modules that we need.
44+
//
45+
const {mathjax} = MathJax._.mathjax;
46+
const {SVG} = MathJax._.output.svg_ts;
47+
48+
// Now using https://docs.mathjax.org/en/v3.2-latest/upgrading/v2.html#version-2-compatibility-example
49+
//
50+
// Replace the require command map with a new one that checks for
51+
// renamed extensions and converts them to the new names.
52+
//
53+
var CommandMap = MathJax._.input.tex.SymbolMap.CommandMap;
54+
var requireMap = MathJax.config.startup.requireMap;
55+
var RequireLoad = MathJax._.input.tex.require.RequireConfiguration.RequireLoad;
56+
var RequireMethods = {
57+
Require: function (parser, name) {
58+
var required = parser.GetArgument(name);
59+
if (required.match(/[^_a-zA-Z0-9]/) || required === '') {
60+
throw new TexError('BadPackageName', 'Argument for %1 is not a valid package name', name);
61+
}
62+
if (requireMap.hasOwnProperty(required)) {
63+
required = requireMap[required];
64+
}
65+
RequireLoad(parser, required);
66+
}
67+
};
68+
new CommandMap('require', {require: 'Require'}, RequireMethods);
69+
MathJax.Callback = function (args) {
70+
if (Array.isArray(args)) {
71+
if (args.length === 1 && typeof(args[0]) === 'function') {
72+
return args[0];
73+
} else if (typeof(args[0]) === 'string' && args[1] instanceof Object &&
74+
typeof(args[1][args[0]]) === 'function') {
75+
return Function.bind.apply(args[1][args[0]], args.slice(1));
76+
} else if (typeof(args[0]) === 'function') {
77+
return Function.bind.apply(args[0], [window].concat(args.slice(1)));
78+
} else if (typeof(args[1]) === 'function') {
79+
return Function.bind.apply(args[1], [args[0]].concat(args.slice(2)));
80+
}
81+
} else if (typeof(args) === 'function') {
82+
return args;
83+
}
84+
throw Error("Can't make callback from given data");
85+
};
86+
//
87+
// Add a replacement for MathJax.Hub commands
88+
//
89+
MathJax.Hub = {
90+
Queue: function () {
91+
for (var i = 0, m = arguments.length; i < m; i++) {
92+
var fn = MathJax.Callback(arguments[i]);
93+
MathJax.startup.promise = MathJax.startup.promise.then(fn);
94+
}
95+
return MathJax.startup.promise;
96+
},
97+
Typeset: function (element, callback) {
98+
var promise = MathJax.typesetSVGPromise([element]).then(
99+
() => {
100+
element.firstElementChild.classList.add("MathJax_SVG");
101+
}
102+
);
103+
if (callback) {
104+
promise = promise.then(callback);
105+
}
106+
return promise;
107+
},
108+
Config: function () {},
109+
Configured: function () {console.log('MathJax cannot be configured like this')},
110+
config: {menuSettings: {renderer: "SVG"}}
111+
};
112+
113+
MathJax.startup.defaultReady();
114+
115+
// Continuing from https://github.com/mathjax/MathJax/issues/2705
116+
//
117+
// Create an SVG output jax and a new MathDocument that uses it.
118+
//
119+
const svgOutput = new SVG(MathJax.config.svg);
120+
const svgDocument = mathjax.document(document, {
121+
...MathJax.config.options,
122+
InputJax: MathJax.startup.input,
123+
OutputJax: svgOutput
124+
});
125+
//
126+
// Define the SVG-based conversion methods
127+
//
128+
MathJax.svgStylesheet = () => svgOutput.styleSheet(svgDocument);
129+
MathJax.typesetSVGPromise = (elements) => {
130+
svgDocument.options.elements = elements;
131+
svgDocument.reset();
132+
return mathjax.handleRetriesFor(() => {
133+
svgDocument.render();
134+
});
135+
};
136+
}
137+
},
138+
loader: {load: ["output/svg"]},
139+
tex: {
140+
inlineMath: [["\\(", "\\)"], ["$", "$"]],
141+
displayMath: [["\\[", "\\]"], ["$$", "$$"]],
142+
processEscapes: true,
143+
processEnvironments: true,
144+
autoload: {
145+
color: [], // don't autoload the color extension
146+
colorv2: ['color'], // do autoload the colorv2 extension
147+
}
148+
}
149+
};
150+
</script>
151+
<script src="../../node_modules/mathjax-v3/es5/tex-mml-chtml.js"></script>
152+
<script>
153+
// let plotly.js know that v2 API is mocked
154+
window.MathJax._mockedV2API = true;
155+
</script>
156+
<script charset="utf-8" id="source" type="module">import "../../build/plotly.js"</script>
157+
<script charset="utf-8" src="../../build/test_dashboard-bundle.js"></script>
158+
</body>
159+
</html>

devtools/test_dashboard/server.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var args = minimist(process.argv.slice(2), {});
1414
var PORT = args.port || 3000;
1515
var strict = args.strict;
1616
var mathjax3 = args.mathjax3;
17+
var mathjax3chtml = args.mathjax3chtml;
1718

1819
// Create server
1920
var server = http.createServer(ecstatic({
@@ -28,7 +29,8 @@ var bundlePlotly = makeWatchifiedBundle(strict, function() {
2829
// open up browser window on first bundle callback
2930
open('http://localhost:' + PORT + '/devtools/test_dashboard/index' + (
3031
strict ? '-strict' :
31-
mathjax3 ? '-mathjax3' : ''
32+
mathjax3 ? '-mathjax3' :
33+
mathjax3chtml ? '-mathjax3chtml' : ''
3234
) + '.html');
3335
});
3436

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"test-plain-obj": "node tasks/test_plain_obj.js",
5454
"test": "npm run test-jasmine -- --nowatch && npm run test-bundle && npm run test-image && npm run test-export && npm run test-syntax && npm run lint",
5555
"mathjax3": "node devtools/test_dashboard/server.js --mathjax3",
56+
"mathjax3chtml": "node devtools/test_dashboard/server.js --mathjax3chtml",
5657
"strict": "node devtools/test_dashboard/server.js --strict",
5758
"start": "node devtools/test_dashboard/server.js",
5859
"baseline": "node test/image/make_baseline.js",

src/lib/svg_text_utils.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,17 @@ function texToSVG(_texString, _config, _callback) {
178178
(MathJax.version || '').split('.')[0]
179179
) || -1;
180180

181+
if(MathJax._mockedV2API) {
182+
MathJaxVersion = 2;
183+
} else if(
184+
MathJaxVersion === 3 &&
185+
MathJax.config.startup.output === 'chtml'
186+
) {
187+
Lib.warn('To use both chtml and svg outputs on the page you may consider mocking MathJax-v2 API as illustrated in devtools/test_dashboard/index-mathjax3chtml.html');
188+
}
189+
181190
if(!MathJaxVersion) {
182-
Lib.log('No MathJax version:', MathJax.version);
191+
Lib.warn('No MathJax version:', MathJax.version);
183192
}
184193

185194
var originalRenderer,

0 commit comments

Comments
 (0)