diff options
Diffstat (limited to 'testing/web-platform/tests/mathml/support/feature-detection.js')
-rw-r--r-- | testing/web-platform/tests/mathml/support/feature-detection.js | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/testing/web-platform/tests/mathml/support/feature-detection.js b/testing/web-platform/tests/mathml/support/feature-detection.js new file mode 100644 index 0000000000..8b3f227d44 --- /dev/null +++ b/testing/web-platform/tests/mathml/support/feature-detection.js @@ -0,0 +1,325 @@ +// 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 <mrow> 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", "<math>\ +<mfrac>\ + <mspace height='50px' depth='50px'></mspace>\ + <mspace height='50px' depth='50px'></mspace>\ +</mfrac>\ +<mfrac>\ + <mspace height='60px' depth='60px'></mspace>\ + <mspace height='60px' depth='60px'></mspace>\ +</mfrac>\ +</math>"); + 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", "<math>\ +<mspace></mspace>\ +<mspace width='20px'></mspace>\ +</math>"); + 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", "<math>\ +<mrow style='font-size: 20px !important'>\ + <mtext>A</mtext>\ +</mrow>\ +<msqrt style='font-size: 20px !important'>\ + <mtext>A</mtext>\ +</msqrt>\ +</math>"); + 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", "<math>\ +<munderover>\ + <mspace width='20px'></mspace>\ + <mspace width='20px'></mspace>\ + <mspace width='20px'></mspace>\ +</munderover>\ +<munderover>\ + <mspace width='40px'></mspace>\ + <mspace width='40px'></mspace>\ + <mspace width='40px'></mspace>\ +</munderover>\ +</math>"); + 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", "<math style='direction: ltr !important;'>\ +<mtext dir='rtl'></mtext>\ +</math>"); + 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", "<math style='font-size: 64px !important;'>\ +<mtext mathsize='32px'></mtext>\ +</math>"); + 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", "<math>\ +<munder>\ + <mo style='font-size: 30px !important' movablelimits='false'>A</mo>\ + <mspace width='100px'></mspace>\ +</munder>\ +<munder>\ + <mo style='font-size: 30px !important' movablelimits='true'>A</mo>\ + <mspace width='100px'></mspace>\ +</munder>\ +</math>"); + var math = document.body.lastElementChild; + var munder = math.getElementsByTagName("munder"); + // If movablelimits is supported, the <mspace> will be placed next + // to <mo> rather than below it, so width_delta is about the width + // of the <mo>. + 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", "<math>\ +<mrow>\ + <mn>1</mn><mo lspace='0px' rspace='0px'>+</mo><mn>2</mn>\ +</mrow>\ +<mrow>\ + <mn>1</mn><mo lspace='20px' rspace='20px'>+</mo><mn>2</mn>\ +</mrow>\ +</math>"); + 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", "\ +<div style='width: 10px !important; height: 10px !important;\ + position: absolute !important;\ + left: 0 !important; top: 0 !important;\ + background: red !important; z-index: 1000 !important;'></div>"); + } + } +}; |