diff --git a/src/Markdown.js b/src/Markdown.js
index 329dcdd996..564a2ed0a8 100644
--- a/src/Markdown.js
+++ b/src/Markdown.js
@@ -23,19 +23,47 @@ const ALLOWED_HTML_TAGS = ['sub', 'sup', 'del', 'u'];
// These types of node are definitely text
const TEXT_NODES = ['text', 'softbreak', 'linebreak', 'paragraph', 'document'];
-function is_math_node(node) {
- return node != null &&
- node.literal != null &&
- node.literal.match(/^<((div|span) data-mx-maths="[^"]*"|\/(div|span))>$/) != null;
+// prevent renderer from interpreting contents of AST node
+function freeze_node(walker, node) {
+ const newNode = new commonmark.Node('custom_inline', node.sourcepos);
+ newNode.onEnter = node.literal;
+ node.insertAfter(newNode);
+ node.unlink();
+ walker.resumeAt(newNode.next, true);
+}
+
+// prevent renderer from interpreting contents of latex math tags
+function freeze_math(parsed) {
+ const walker = parsed.walker();
+ let ev;
+ let inMath = false;
+ while ( (ev = walker.next()) ) {
+ const node = ev.node;
+ if (ev.entering) {
+ if (!inMath) {
+ // entering a math tag
+ if (node.literal != null && node.literal.match('^<(div|span) data-mx-maths="[^"]*">$') != null) {
+ inMath = true;
+ freeze_node(walker, node);
+ }
+ } else {
+ // math tags should only contain a single code block, with URL-escaped latex as fallback output
+ if (node.literal != null && node.literal.match('^(|
|[^<>]*)$')) {
+ freeze_node(walker, node);
+ // leave when span or div is closed
+ } else if (node.literal == '' || node.literal == '') {
+ inMath = false;
+ freeze_node(walker, node);
+ // this case only happens if we have improperly formatted math tags, so bail
+ } else {
+ inMath = false;
+ }
+ }
+ }
+ }
}
function is_allowed_html_tag(node) {
- if (SettingsStore.getValue("feature_latex_maths") &&
- (is_math_node(node) ||
- (node.literal.match(/^<\/?code>$/) && is_math_node(node.parent)))) {
- return true;
- }
-
// Regex won't work for tags with attrs, but we only
// allow anyway.
const matches = /^<\/?(.*)>$/.exec(node.literal);
@@ -173,6 +201,9 @@ export default class Markdown {
*/
};
+ // prevent strange behaviour when mixing latex math and markdown
+ freeze_math(this.parsed);
+
return renderer.render(this.parsed);
}