// This is a helper for MathML feature detection. // It is indented to be used to prevent false negative test results. var MathMLFeatureDetection = { "has_annotation": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_annotation-xml": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_maction": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_math": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_menclose": function() { // Just check whether is supported because discussion on this is // still open ( https://github.com/mathml-refresh/mathml/issues/105 ) // and it would have to behave at least like an mrow, even if it becomes // an unknown element at the end. return this.has_mrow(); }, "has_merror": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mfrac": function() { if (!this.hasOwnProperty("_has_mfrac")) { // Use tall enough fraction to avoid side effect of min num/denum shifts. document.body.insertAdjacentHTML("beforeend", "\ \ \ \ \ \ \ \ \ "); var math = document.body.lastElementChild; var mfrac = math.getElementsByTagName("mfrac"); // height/depth will add 40px per MathML, 20px if mfrac does not stack its children and none if mspace is not supported. this._has_mfrac = mfrac[1].getBoundingClientRect().height - mfrac[0].getBoundingClientRect().height > 30; document.body.removeChild(math); } return this._has_mfrac; }, "has_mi": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mmultiscripts": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mn": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mo": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mover": function() { // FIXME: Improve feature detection. return this.has_munderover(); }, "has_mpadded": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mphantom": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mprescripts": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mroot": function() { // FIXME: Improve feature detection. return this.has_msqrt(); }, "has_mrow": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_ms": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mspace": function() { // https://w3c.github.io/mathml-core/#space-mspace if (!this.hasOwnProperty("_has_mspace")) { document.body.insertAdjacentHTML("beforeend", "\ \ \ "); var math = document.body.lastElementChild; // The width attribute will add 20px per MathML and none if not supported. this._has_mspace = math.lastChild.getBoundingClientRect().width - math.firstChild.getBoundingClientRect().width > 10; document.body.removeChild(math); } return this._has_mspace; }, "has_msqrt": function() { if (!this.hasOwnProperty("_has_msqrt")) { document.body.insertAdjacentHTML("beforeend", "\ \ A\ \ \ A\ \ "); var math = document.body.lastElementChild; // The radical symbol will make msqrt wider than mrow, if the former is supported. this._has_msqrt = math.lastElementChild.getBoundingClientRect().width - math.firstElementChild.getBoundingClientRect().width > 5; document.body.removeChild(math); } return this._has_msqrt; }, "has_mstyle": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_msub": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_msubsup": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_msup": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mtable": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mtd": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mtext": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_mtr": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_munder": function() { // FIXME: Improve feature detection. return this.has_munderover(); }, "has_munderover": function() { if (!this.hasOwnProperty("_has_munderover")) { document.body.insertAdjacentHTML("beforeend", "\ \ \ \ \ \ \ \ \ \ \ "); var math = document.body.lastElementChild; var munderover = math.getElementsByTagName("munderover"); // width_delta will be 20px per MathML, 3 * 20 = 60px if mundeover does not stack its children and 0px if mspace is not supported. var width_delta = munderover[1].getBoundingClientRect().width - munderover[0].getBoundingClientRect().width; this._has_munderover = width_delta > 10 && width_delta < 30; document.body.removeChild(math); } return this._has_munderover; }, "has_none": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_semantics": function() { // FIXME: Improve feature detection. return this.has_mspace(); }, "has_dir": function() { if (!this.hasOwnProperty("_has_dir")) { document.body.insertAdjacentHTML("beforeend", "\ \ "); var math = document.body.lastElementChild; this._has_dir = window.getComputedStyle(math.firstElementChild). getPropertyValue('direction') === 'rtl'; document.body.removeChild(math); } return this._has_dir; }, "has_mathsize": function() { if (!this.hasOwnProperty("_has_mathsize")) { document.body.insertAdjacentHTML("beforeend", "\ \ "); var math = document.body.lastElementChild; this._has_mathsize = window.getComputedStyle(math.firstElementChild). getPropertyValue('font-size') === '32px'; document.body.removeChild(math); } return this._has_mathsize; }, "has_movablelimits": function() { if (!this.hasOwnProperty("_has_movablelimits")) { document.body.insertAdjacentHTML("beforeend", "\ \ A\ \ \ \ A\ \ \ "); var math = document.body.lastElementChild; var munder = math.getElementsByTagName("munder"); // If movablelimits is supported, the will be placed next // to rather than below it, so width_delta is about the width // of the . var width_delta = munder[1].getBoundingClientRect().width - munder[0].getBoundingClientRect().width; this._has_movablelimits = this.has_munder() && width_delta > 20; document.body.removeChild(math); } return this._has_movablelimits; }, "has_operator_spacing": function() { // https://w3c.github.io/mathml-core/#dfn-lspace // https://w3c.github.io/mathml-core/#layout-of-mrow if (!this.hasOwnProperty("_has_operator_spacing")) { document.body.insertAdjacentHTML("beforeend", "\ \ 1+2\ \ \ 1+2\ \ "); var math = document.body.lastElementChild; var mrow = math.getElementsByTagName("mrow"); // lspace/rspace will add 40px per MathML and none if not supported. this._has_operator_spacing = mrow[1].getBoundingClientRect().width - mrow[0].getBoundingClientRect().width > 30; document.body.removeChild(math); } return this._has_operator_spacing; }, ensure_for_match_reftest: function(has_function) { if (!document.querySelector("link[rel='match']")) throw "This function must only be used for match reftest"; // Add a little red square at the top left corner if the feature is not supported in order to make match reftest fail. if (!this[has_function]()) { document.body.insertAdjacentHTML("beforeend", "\
"); } } };