From 782282561b3d2b7788c97c56f4924c064435ac5b Mon Sep 17 00:00:00 2001 From: Christopher Cameron Date: Tue, 6 May 2025 23:14:43 +0200 Subject: [PATCH 1/6] Add MathJax workaround --- js/validate.mjs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/js/validate.mjs b/js/validate.mjs index 5b11c9c..ffa3d8a 100644 --- a/js/validate.mjs +++ b/js/validate.mjs @@ -159,8 +159,12 @@ class EqDivMatcher { if (element.localName !== "div" || element.className !== "formula") return false; - if (element.childElementCount !== 1 || element.firstElementChild.localName !== "math") - logger.error(`Formula div must contain a single math element`, element); + // TODO: MathJax formulas aren't encased in elements. + // https://github.com/SMPTE/html-pub/issues/156 + if (element.childElementCount !== 0) { + if (element.childElementCount !== 1 || element.firstElementChild.localName !== "math") + logger.error(`Formula div must contain a single math element`, element); + } if (element.id === null) logger.error("Formula div is missing an id attribute", element); @@ -904,4 +908,4 @@ function validateBody(body, logger) { } return true; -} \ No newline at end of file +} From 182d9e20efc36deff56d64ff4e287c1dfadae369 Mon Sep 17 00:00:00 2001 From: Christopher Cameron Date: Sat, 19 Jul 2025 14:33:09 -0700 Subject: [PATCH 2/6] Allow MathJax CHTML to validate --- js/validate.mjs | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/js/validate.mjs b/js/validate.mjs index ffa3d8a..4cdb7ba 100644 --- a/js/validate.mjs +++ b/js/validate.mjs @@ -101,6 +101,26 @@ class MathMatcher { } } +class MathJaxMatcher { + constructor(localName) { + this.localName = localName; + } + + match(element, logger) { + if (element.localName !== this.localName) + return false; + + for (const child of element.children) { + if (child.localName != 'mjx-math' && + child.localName != 'mjx-assistive-mml' && + child.localName != 'svg') { + logger.error(`MathJax container has unexpected child ` + child.localName, element); + } + } + + return true; + } +} const ALL_PHRASING_MATCHERS = [ new TerminalPhrasingMatcher("abbr"), @@ -126,7 +146,8 @@ const ALL_PHRASING_MATCHERS = [ new PhrasingMatcher("u"), new TerminalPhrasingMatcher("var"), new TerminalPhrasingMatcher("wbr"), - new TerminalPhrasingMatcher("a") + new TerminalPhrasingMatcher("a"), + new MathJaxMatcher("mjx-container") ]; class AnyPhrasingMatcher { static match(element, logger) { @@ -162,8 +183,11 @@ class EqDivMatcher { // TODO: MathJax formulas aren't encased in elements. // https://github.com/SMPTE/html-pub/issues/156 if (element.childElementCount !== 0) { - if (element.childElementCount !== 1 || element.firstElementChild.localName !== "math") - logger.error(`Formula div must contain a single math element`, element); + if (element.childElementCount !== 1 || + (element.firstElementChild.localName !== "math" && + element.firstElementChild.localName !== "mjx-container")) { + logger.error(`Formula div must contain a single math or mjx-container element`, element); + } } if (element.id === null) From e33879c09ea5cd3f32166c9891017f0e32797acf Mon Sep 17 00:00:00 2001 From: Christopher Cameron Date: Sat, 19 Jul 2025 14:46:20 -0700 Subject: [PATCH 3/6] Remove MathML MathJax workaround --- js/validate.mjs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/js/validate.mjs b/js/validate.mjs index 4cdb7ba..868fdf7 100644 --- a/js/validate.mjs +++ b/js/validate.mjs @@ -180,14 +180,10 @@ class EqDivMatcher { if (element.localName !== "div" || element.className !== "formula") return false; - // TODO: MathJax formulas aren't encased in elements. - // https://github.com/SMPTE/html-pub/issues/156 - if (element.childElementCount !== 0) { - if (element.childElementCount !== 1 || - (element.firstElementChild.localName !== "math" && - element.firstElementChild.localName !== "mjx-container")) { - logger.error(`Formula div must contain a single math or mjx-container element`, element); - } + if (element.childElementCount !== 1 || + (element.firstElementChild.localName !== "math" && + element.firstElementChild.localName !== "mjx-container")) { + logger.error(`Formula div must contain a single math or mjx-container element`, element); } if (element.id === null) From e4f6b5fbccbbe633db0ce69d5a534d88a9156cbe Mon Sep 17 00:00:00 2001 From: Christopher Cameron Date: Mon, 21 Jul 2025 17:18:51 -0700 Subject: [PATCH 4/6] Add mathjax pre-parsing support --- js/validate.mjs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/js/validate.mjs b/js/validate.mjs index 868fdf7..9eff1c0 100644 --- a/js/validate.mjs +++ b/js/validate.mjs @@ -180,16 +180,24 @@ class EqDivMatcher { if (element.localName !== "div" || element.className !== "formula") return false; - if (element.childElementCount !== 1 || - (element.firstElementChild.localName !== "math" && - element.firstElementChild.localName !== "mjx-container")) { - logger.error(`Formula div must contain a single math or mjx-container element`, element); + // MathJax formulas, prior to parsing, will have the latex formula source in + // \[ \] or $$ $$. After parsing, they will be replaced with an + // mjx-container element. + if (element.childElementCount === 0) { + if (element.innerText.match(/\[.*\]/) || + element.innerText.match(/$$.*$$/)) { + return true; + } } + if (element.childElementCount === 1) { + if (element.firstElementChild.localName === "math" || + element.firstElementChild.localName === "mjx-container") { + return true; + } + } + logger.error(`Formula div must contain a single math or mjx-container element`, element); - if (element.id === null) - logger.error("Formula div is missing an id attribute", element); - - return true; + return false; } } From da6291307a2ecb9ffbcfa066ace47e461ff3f8cf Mon Sep 17 00:00:00 2001 From: Christopher Cameron Date: Mon, 21 Jul 2025 17:31:20 -0700 Subject: [PATCH 5/6] Use textContent --- js/validate.mjs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/js/validate.mjs b/js/validate.mjs index 9eff1c0..1cdfcb1 100644 --- a/js/validate.mjs +++ b/js/validate.mjs @@ -180,12 +180,10 @@ class EqDivMatcher { if (element.localName !== "div" || element.className !== "formula") return false; - // MathJax formulas, prior to parsing, will have the latex formula source in - // \[ \] or $$ $$. After parsing, they will be replaced with an - // mjx-container element. if (element.childElementCount === 0) { - if (element.innerText.match(/\[.*\]/) || - element.innerText.match(/$$.*$$/)) { + console.log(element.textContent); + if (element.textContent.match(/\[.*\]/) || + element.textContent.match(/$$.*$$/)) { return true; } } @@ -196,8 +194,7 @@ class EqDivMatcher { } } logger.error(`Formula div must contain a single math or mjx-container element`, element); - - return false; + return true; } } From 348386f1a92a67e0e8f670e5fd10a02a269fc69a Mon Sep 17 00:00:00 2001 From: Christopher Cameron Date: Tue, 22 Jul 2025 10:47:23 -0700 Subject: [PATCH 6/6] Add comment, remove log --- js/validate.mjs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/js/validate.mjs b/js/validate.mjs index 1cdfcb1..4927dc7 100644 --- a/js/validate.mjs +++ b/js/validate.mjs @@ -180,8 +180,11 @@ class EqDivMatcher { if (element.localName !== "div" || element.className !== "formula") return false; + // MathJax will asynchronously replace latex equations written in + // textContent, escaped by $$ $$ or \[ \] delimiters, with an mjx-container + // element. If MathJax has yet not performed this processing, then ensure + // that the equation div have an escaped block equation in its textContent. if (element.childElementCount === 0) { - console.log(element.textContent); if (element.textContent.match(/\[.*\]/) || element.textContent.match(/$$.*$$/)) { return true;