Skip to content
Open
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
2 changes: 1 addition & 1 deletion xblocks_contrib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
from .video import VideoBlock
from .word_cloud import WordCloudBlock

__version__ = "0.17.0"
__version__ = "0.17.1"
Original file line number Diff line number Diff line change
@@ -1,56 +1,35 @@
// See common/templates/mathjax_include.html for info on Fast Preview mode.
var disableFastPreview = true,
vendorScript;
if (typeof MathJax === 'undefined') {
if (disableFastPreview) {
window.MathJax = {
menuSettings: {CHTMLpreview: false}
};
}

vendorScript = document.createElement('script');
vendorScript.onload = function() {
'use strict';

var MathJax = window.MathJax,
setMathJaxDisplayDivSettings;
MathJax.Hub.Config({
tex2jax: {
inlineMath: [
['\\(', '\\)'],
['[mathjaxinline]', '[/mathjaxinline]']
],
displayMath: [
['\\[', '\\]'],
['[mathjax]', '[/mathjax]']
]
}
});
if (disableFastPreview) {
MathJax.Hub.processSectionDelay = 0;
}
MathJax.Hub.signal.Interest(function(message) {
if (message[0] === 'End Math') {
setMathJaxDisplayDivSettings();
}
});
setMathJaxDisplayDivSettings = function() {
$('.MathJax_Display').each(function() {
this.setAttribute('tabindex', '0');
this.setAttribute('aria-live', 'off');
this.removeAttribute('role');
this.removeAttribute('aria-readonly');
});
};
};
// Automatic loading of Mathjax accessibility files
window.MathJax = {
menuSettings: {
collapsible: true,
autocollapse: false,
explorer: true
tex: {
inlineMath: [
['\\(', '\\)'],
['[mathjaxinline]', '[/mathjaxinline]']
],
displayMath: [
['\\[', '\\]'],
['[mathjax]', '[/mathjax]']
],
autoload: {
color: [],
colorv2: ['color']
},
packages: {'[+]': ['noerrors']}
},
options: {
ignoreHtmlClass: 'tex2jax_ignore',
processHtmlClass: 'tex2jax_process',
menuOptions: {
settings: {
collapsible: true,
explorer: true
},
},
},
loader: {
load: ['input/asciimath', '[tex]/noerrors']
}
};
vendorScript.src = 'https://cdn.jsdelivr.net/npm/mathjax@2.7.5/MathJax.js?config=TeX-MML-AM_HTMLorMML';
var vendorScript = document.createElement('script');
vendorScript.src = 'https://cdn.jsdelivr.net/npm/mathjax@4.1.2/tex-mml-chtml.js';
document.body.appendChild(vendorScript);
}
8 changes: 6 additions & 2 deletions xblocks_contrib/discussion/assets/static/js/common/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,8 +493,12 @@
};

DiscussionUtil.typesetMathJax = function(element) {
if (typeof MathJax !== 'undefined' && MathJax !== null && typeof MathJax.Hub !== 'undefined') {
MathJax.Hub.Queue(['Typeset', MathJax.Hub, element[0]]);
if (typeof MathJax !== 'undefined' && MathJax !== null &&
typeof MathJax.startup !== 'undefined' && MathJax.startup !== null &&
typeof MathJax.startup.promise !== 'undefined' &&
typeof MathJax.typesetPromise === 'function') {
MathJax.startup.promise
.then(() => MathJax.typesetPromise([element[0]]));
}
};

Expand Down
2 changes: 1 addition & 1 deletion xblocks_contrib/discussion/assets/static/js/customwmd.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Mostly adapted from math.stackexchange.com: http://cdn.sstatic.net/js/mathjax-ed
MathJaxProcessor.prototype.processMath = function(start, last, preProcess) {
var block, i, j, ref, ref1;
block = this.blocks.slice(start, last + 1).join("").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
if (MathJax.Hub.Browser.isMSIE) {
if (window.navigator && /msie|trident/i.test(window.navigator.userAgent)) {
block = block.replace(/(%[^\n]*)\n/g, "$1<br/>\n");
}
for (i = j = ref = start + 1, ref1 = last; ref <= ref1 ? j <= ref1 : j >= ref1; i = ref <= ref1 ? ++j : --j) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

MathJaxDelayRenderer.prototype.maxDelay = 3000;

MathJaxDelayRenderer.prototype.mathjaxRunning = false;

MathJaxDelayRenderer.prototype.elapsedTime = 0;

MathJaxDelayRenderer.prototype.mathjaxDelay = 0;
Expand Down Expand Up @@ -59,8 +57,15 @@
if (preprocessor != null) {
text = preprocessor(text);
}
if (typeof MathJax !== 'undefined' && MathJax !== null && typeof MathJax.typesetClear === 'function') {
MathJax.typesetClear([$(elem)[0]]);
}
$(elem).html(text); // xss-lint: disable=javascript-jquery-html
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, $(elem).attr("id")]);
if (typeof MathJax !== 'undefined' && MathJax !== null && MathJax.startup &&
MathJax.startup.promise && typeof MathJax.typesetPromise === "function") {
return MathJax.startup.promise
.then(() => MathJax.typesetPromise([$(elem)[0]]));
}
} else {
if (this.mathjaxTimeout) {
window.clearTimeout(this.mathjaxTimeout);
Expand All @@ -70,31 +75,38 @@
renderer = (function(_this) {
return function() {
var curTime, prevTime;
if (_this.mathjaxRunning) {
return;
}
prevTime = getTime();
if (preprocessor != null) {
text = preprocessor(text);
}
if (typeof MathJax !== 'undefined' && MathJax !== null && typeof MathJax.typesetClear === 'function') {
MathJax.typesetClear([_this.$buffer[0]]);
}
_this.$buffer.html(text); // xss-lint: disable=javascript-jquery-html
curTime = getTime();
_this.elapsedTime = curTime - prevTime;
if (typeof MathJax !== "undefined" && MathJax !== null) {
if (typeof MathJax !== "undefined" && MathJax !== null && MathJax.startup &&
MathJax.startup.promise && typeof MathJax.typesetPromise === "function") {
prevTime = getTime();
_this.mathjaxRunning = true;
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, _this.$buffer.attr("id")], function() {
_this.mathjaxRunning = false;
curTime = getTime();
_this.mathjaxDelay = curTime - prevTime;
if (previewSetter) {
return previewSetter($(_this.$buffer).html());
} else {
return $(elem).html($(_this.$buffer).html()); // xss-lint: disable=javascript-jquery-html
}
});
return MathJax.startup.promise
.then(
() => MathJax.typesetPromise([_this.$buffer[0]]).then(() => {
curTime = getTime();
_this.mathjaxDelay = curTime - prevTime;
if (previewSetter) {
return previewSetter($(_this.$buffer).html());
} else {
return $(elem).html($(_this.$buffer).html()); // xss-lint: disable=javascript-jquery-html
}
})
);
} else {
return _this.mathjaxDelay = 0;
_this.mathjaxDelay = 0;
if (previewSetter) {
return previewSetter($(_this.$buffer).html());
} else {
return $(elem).html($(_this.$buffer).html()); // xss-lint: disable=javascript-jquery-html
}
}
};
})(this);
Expand Down
12 changes: 11 additions & 1 deletion xblocks_contrib/html/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,17 @@ def student_view(self, _context):
"""Return a fragment that contains the html for the student view."""
frag = Fragment(self.get_html())
frag.add_css(resource_loader.load_unicode("static/css/html.css"))
frag.add_javascript("""function HtmlBlock(runtime, element){}""")
frag.add_javascript("""
function HtmlBlock(runtime, element) {
if (typeof MathJax !== "undefined" && MathJax !== null &&
MathJax.startup && MathJax.startup.promise &&
typeof MathJax.typesetPromise === "function") {
MathJax.startup.promise.then(function() {
MathJax.typesetPromise([element]);
});
}
}
""")
frag.initialize_js("HtmlBlock")
return frag

Expand Down
47 changes: 28 additions & 19 deletions xblocks_contrib/problem/assets/spec/display_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ describe("Problem", function () {
var mockRuntime = {};

beforeEach(function () {
// Stub MathJax
// Stub MathJax v3/v4 API
window.MathJax = {
Hub: jasmine.createSpyObj("MathJax.Hub", ["getAllJax", "Queue"]),
Callback: jasmine.createSpyObj("MathJax.Callback", ["After"]),
startup: {
promise: { then: function(cb) { cb(); return this; }, catch: function() { return this; } },
document: {
getMathItemsWithin: jasmine.createSpy("getMathItemsWithin"),
},
toMML: jasmine.createSpy("startup.toMML"),
},
typesetPromise: jasmine.createSpy("typesetPromise"),
typesetClear: jasmine.createSpy("typesetClear"),
};
this.stubbedJax = { root: jasmine.createSpyObj("jax.root", ["toMathML"]) };
MathJax.Hub.getAllJax.and.returnValue([this.stubbedJax]);
this.stubbedJax = { root: {} };
MathJax.startup.document.getMathItemsWithin.and.returnValue([this.stubbedJax]);
MathJax.startup.toMML.and.returnValue("<MathML>");
MathJax.typesetPromise.and.returnValue(Promise.resolve());
window.update_schematics = function () {};
spyOn(SR, "readText");
spyOn(SR, "readTexts");
Expand Down Expand Up @@ -58,11 +67,10 @@ data-url='/problem/quiz/'> \
describe("bind", function () {
beforeEach(function () {
spyOn(window, "update_schematics");
MathJax.Hub.getAllJax.and.returnValue([this.stubbedJax]);
this.problem = new Problem(mockRuntime, $(".xblock-student_view"));
});

it("set mathjax typeset", () => expect(MathJax.Hub.Queue).toHaveBeenCalled());
it("set mathjax typeset", () => expect(MathJax.typesetPromise).toHaveBeenCalled());

it("update schematics", () => expect(window.update_schematics).toHaveBeenCalled());

Expand Down Expand Up @@ -94,7 +102,6 @@ data-url='/problem/quiz/'> \
describe("bind_with_custom_input_id", function () {
beforeEach(function () {
spyOn(window, "update_schematics");
MathJax.Hub.getAllJax.and.returnValue([this.stubbedJax]);
this.problem = new Problem(mockRuntime, $(".xblock-student_view"));
return $(this).html(readFixtures("problem_content_1240.html"));
});
Expand Down Expand Up @@ -999,38 +1006,40 @@ data-url='/problem/quiz/'> \
this.problem.refreshMath({ target: $("#input_example_1").get(0) });
});

it("should queue the conversion and MathML element update", function () {
expect(MathJax.Hub.Queue).toHaveBeenCalledWith(
["Text", this.stubbedJax, "E=mc^2"],
[this.problem.updateMathML, this.stubbedJax, $("#input_example_1").get(0)],
);
it("should trigger MathJax v4 typesetting via typesetClear + typesetPromise", function () {
expect(MathJax.typesetClear).toHaveBeenCalled();
expect(MathJax.typesetPromise).toHaveBeenCalled();
});
});

describe("updateMathML", function () {
beforeEach(function () {
this.problem = new Problem(mockRuntime, $(".xblock-student_view"));
this.stubbedJax.root.toMathML.and.returnValue("<MathML>");
});

describe("when there is no exception", function () {
beforeEach(function () {
this.problem.updateMathML(this.stubbedJax, $("#input_example_1").get(0));
});

it("convert jax to MathML", () => expect($("#input_example_1_dynamath")).toHaveValue("<MathML>"));
it("convert jax to MathML via startup.toMML", function () {
expect(MathJax.startup.toMML).toHaveBeenCalledWith(this.stubbedJax.root);
expect($("#input_example_1_dynamath")).toHaveValue("<MathML>");
});
});

describe("when there is an exception", function () {
describe("when there is an exception with restart", function () {
beforeEach(function () {
const error = new Error();
error.restart = true;
this.stubbedJax.root.toMathML.and.throwError(error);
MathJax.startup.toMML.and.throwError(error);
this.problem.updateMathML(this.stubbedJax, $("#input_example_1").get(0));
});

it("should queue up the exception", function () {
expect(MathJax.Callback.After).toHaveBeenCalledWith([this.problem.refreshMath, this.stubbedJax], true);
it("should catch the error and not propagate", function () {
// v4: caught by try/catch, restart=true → startup.promise.then schedules refreshMath.
// Minimal assertion: toMML was invoked, no uncaught exception.
expect(MathJax.startup.toMML).toHaveBeenCalled();
});
});
});
Expand Down
Loading