tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

feature-detection.js (10765B)


      1 // This is a helper for MathML feature detection.
      2 // It is indented to be used to prevent false negative test results.
      3 
      4 var MathMLFeatureDetection = {
      5 
      6    "has_annotation": function() {
      7        // FIXME: Improve feature detection.
      8        return this.has_mspace();
      9    },
     10 
     11    "has_annotation-xml": function() {
     12        // FIXME: Improve feature detection.
     13        return this.has_mspace();
     14    },
     15 
     16    "has_maction": function() {
     17        // FIXME: Improve feature detection.
     18        return this.has_mspace();
     19    },
     20 
     21    "has_math": function() {
     22        // FIXME: Improve feature detection.
     23        return this.has_mspace();
     24    },
     25 
     26    "has_menclose": function() {
     27        // Just check whether <mrow> is supported because discussion on this is
     28        // still open ( https://github.com/mathml-refresh/mathml/issues/105 )
     29        // and it would have to behave at least like an mrow, even if it becomes
     30        // an unknown element at the end.
     31        return this.has_mrow();
     32    },
     33 
     34    "has_merror": function() {
     35        // FIXME: Improve feature detection.
     36        return this.has_mspace();
     37    },
     38 
     39    "has_mfrac": function() {
     40        if (!this.hasOwnProperty("_has_mfrac")) {
     41            // Use tall enough fraction to avoid side effect of min num/denum shifts.
     42            document.body.insertAdjacentHTML("beforeend", "<math>\
     43 <mfrac>\
     44  <mspace height='50px' depth='50px'></mspace>\
     45  <mspace height='50px' depth='50px'></mspace>\
     46 </mfrac>\
     47 <mfrac>\
     48  <mspace height='60px' depth='60px'></mspace>\
     49  <mspace height='60px' depth='60px'></mspace>\
     50 </mfrac>\
     51 </math>");
     52            var math = document.body.lastElementChild;
     53            var mfrac = math.getElementsByTagName("mfrac");
     54            // height/depth will add 40px per MathML, 20px if mfrac does not stack its children and none if mspace is not supported.
     55            this._has_mfrac =
     56                mfrac[1].getBoundingClientRect().height -
     57                mfrac[0].getBoundingClientRect().height > 30;
     58            document.body.removeChild(math);
     59        }
     60        return this._has_mfrac;
     61    },
     62 
     63    "has_mi": function() {
     64        // FIXME: Improve feature detection.
     65        return this.has_mspace();
     66    },
     67 
     68    "has_mmultiscripts": function() {
     69        // FIXME: Improve feature detection.
     70        return this.has_mspace();
     71    },
     72 
     73    "has_mn": function() {
     74        // FIXME: Improve feature detection.
     75        return this.has_mspace();
     76    },
     77 
     78    "has_mo": function() {
     79        // FIXME: Improve feature detection.
     80        return this.has_mspace();
     81    },
     82 
     83    "has_mover": function() {
     84        // FIXME: Improve feature detection.
     85        return this.has_munderover();
     86    },
     87 
     88    "has_mpadded": function() {
     89        // FIXME: Improve feature detection.
     90        return this.has_mspace();
     91    },
     92 
     93    "has_mphantom": function() {
     94        // FIXME: Improve feature detection.
     95        return this.has_mspace();
     96    },
     97 
     98    "has_mprescripts": function() {
     99        // FIXME: Improve feature detection.
    100        return this.has_mspace();
    101    },
    102 
    103    "has_mroot": function() {
    104        // FIXME: Improve feature detection.
    105        return this.has_msqrt();
    106    },
    107 
    108    "has_mrow": function() {
    109        // FIXME: Improve feature detection.
    110        return this.has_mspace();
    111    },
    112 
    113    "has_ms": function() {
    114        // FIXME: Improve feature detection.
    115        return this.has_mspace();
    116    },
    117 
    118    "has_mspace": function() {
    119        // https://w3c.github.io/mathml-core/#space-mspace
    120        if (!this.hasOwnProperty("_has_mspace")) {
    121            document.body.insertAdjacentHTML("beforeend", "<math>\
    122 <mspace></mspace>\
    123 <mspace width='20px'></mspace>\
    124 </math>");
    125            var math = document.body.lastElementChild;
    126            // The width attribute will add 20px per MathML and none if not supported.
    127            this._has_mspace =
    128                math.lastChild.getBoundingClientRect().width -
    129                math.firstChild.getBoundingClientRect().width > 10;
    130            document.body.removeChild(math);
    131        }
    132        return this._has_mspace;
    133    },
    134 
    135    "has_msqrt": function() {
    136        if (!this.hasOwnProperty("_has_msqrt")) {
    137            document.body.insertAdjacentHTML("beforeend", "<math>\
    138 <mrow style='font-size: 20px !important'>\
    139  <mtext>A</mtext>\
    140 </mrow>\
    141 <msqrt style='font-size: 20px !important'>\
    142  <mtext>A</mtext>\
    143 </msqrt>\
    144 </math>");
    145            var math = document.body.lastElementChild;
    146            // The radical symbol will make msqrt wider than mrow, if the former is supported.
    147            this._has_msqrt =
    148                math.lastElementChild.getBoundingClientRect().width -
    149                math.firstElementChild.getBoundingClientRect().width > 5;
    150            document.body.removeChild(math);
    151        }
    152        return this._has_msqrt;
    153    },
    154 
    155    "has_mstyle": function() {
    156        // FIXME: Improve feature detection.
    157        return this.has_mspace();
    158    },
    159 
    160    "has_msub": function() {
    161        // FIXME: Improve feature detection.
    162        return this.has_mspace();
    163    },
    164 
    165    "has_msubsup": function() {
    166        // FIXME: Improve feature detection.
    167        return this.has_mspace();
    168    },
    169 
    170    "has_msup": function() {
    171        // FIXME: Improve feature detection.
    172        return this.has_mspace();
    173    },
    174 
    175    "has_mtable": function() {
    176        // FIXME: Improve feature detection.
    177        return this.has_mspace();
    178    },
    179 
    180    "has_mtd": function() {
    181        // FIXME: Improve feature detection.
    182        return this.has_mspace();
    183    },
    184 
    185    "has_mtext": function() {
    186        // FIXME: Improve feature detection.
    187        return this.has_mspace();
    188    },
    189 
    190    "has_mtr": function() {
    191        // FIXME: Improve feature detection.
    192        return this.has_mspace();
    193    },
    194 
    195    "has_munder": function() {
    196        // FIXME: Improve feature detection.
    197        return this.has_munderover();
    198    },
    199 
    200    "has_munderover": function() {
    201        if (!this.hasOwnProperty("_has_munderover")) {
    202            document.body.insertAdjacentHTML("beforeend", "<math>\
    203 <munderover>\
    204  <mspace width='20px'></mspace>\
    205  <mspace width='20px'></mspace>\
    206  <mspace width='20px'></mspace>\
    207 </munderover>\
    208 <munderover>\
    209  <mspace width='40px'></mspace>\
    210  <mspace width='40px'></mspace>\
    211  <mspace width='40px'></mspace>\
    212 </munderover>\
    213 </math>");
    214            var math = document.body.lastElementChild;
    215            var munderover = math.getElementsByTagName("munderover");
    216            // width_delta will be 20px per MathML, 3 * 20 = 60px if mundeover does not stack its children and 0px if mspace is not supported.
    217            var width_delta =
    218                munderover[1].getBoundingClientRect().width -
    219                munderover[0].getBoundingClientRect().width;
    220            this._has_munderover = width_delta > 10 && width_delta < 30;
    221            document.body.removeChild(math);
    222        }
    223        return this._has_munderover;
    224    },
    225 
    226    "has_none": function() {
    227        // FIXME: Improve feature detection.
    228        return this.has_mspace();
    229    },
    230 
    231    "has_semantics": function() {
    232        // FIXME: Improve feature detection.
    233        return this.has_mspace();
    234    },
    235 
    236    "has_dir": function() {
    237        if (!this.hasOwnProperty("_has_dir")) {
    238            document.body.insertAdjacentHTML("beforeend", "<math style='direction: ltr !important;'>\
    239 <mtext dir='rtl'></mtext>\
    240 </math>");
    241            var math = document.body.lastElementChild;
    242            this._has_dir =
    243                window.getComputedStyle(math.firstElementChild).
    244                getPropertyValue('direction') === 'rtl';
    245            document.body.removeChild(math);
    246        }
    247        return this._has_dir;
    248    },
    249 
    250    "has_mathsize": function() {
    251        if (!this.hasOwnProperty("_has_mathsize")) {
    252            document.body.insertAdjacentHTML("beforeend", "<math style='font-size: 64px !important;'>\
    253 <mtext mathsize='32px'></mtext>\
    254 </math>");
    255            var math = document.body.lastElementChild;
    256            this._has_mathsize =
    257                window.getComputedStyle(math.firstElementChild).
    258                getPropertyValue('font-size') === '32px';
    259            document.body.removeChild(math);
    260        }
    261        return this._has_mathsize;
    262    },
    263 
    264    "has_movablelimits": function() {
    265        if (!this.hasOwnProperty("_has_movablelimits")) {
    266            document.body.insertAdjacentHTML("beforeend", "<math>\
    267 <munder>\
    268  <mo style='font-size: 30px !important' movablelimits='false'>A</mo>\
    269  <mspace width='100px'></mspace>\
    270 </munder>\
    271 <munder>\
    272  <mo style='font-size: 30px !important' movablelimits='true'>A</mo>\
    273  <mspace width='100px'></mspace>\
    274 </munder>\
    275 </math>");
    276            var math = document.body.lastElementChild;
    277            var munder = math.getElementsByTagName("munder");
    278            // If movablelimits is supported, the <mspace> will be placed next
    279            // to <mo> rather than below it, so width_delta is about the width
    280            // of the <mo>.
    281            var width_delta =
    282                munder[1].getBoundingClientRect().width -
    283                munder[0].getBoundingClientRect().width;
    284            this._has_movablelimits = this.has_munder() && width_delta > 20;
    285            document.body.removeChild(math);
    286        }
    287        return this._has_movablelimits;
    288    },
    289 
    290    "has_operator_spacing": function() {
    291        // https://w3c.github.io/mathml-core/#dfn-lspace
    292        // https://w3c.github.io/mathml-core/#layout-of-mrow
    293        if (!this.hasOwnProperty("_has_operator_spacing")) {
    294            document.body.insertAdjacentHTML("beforeend", "<math>\
    295 <mrow>\
    296  <mn>1</mn><mo lspace='0px' rspace='0px'>+</mo><mn>2</mn>\
    297 </mrow>\
    298 <mrow>\
    299  <mn>1</mn><mo lspace='20px' rspace='20px'>+</mo><mn>2</mn>\
    300 </mrow>\
    301 </math>");
    302            var math = document.body.lastElementChild;
    303            var mrow = math.getElementsByTagName("mrow");
    304            // lspace/rspace will add 40px per MathML and none if not supported.
    305            this._has_operator_spacing =
    306                mrow[1].getBoundingClientRect().width -
    307                mrow[0].getBoundingClientRect().width > 30;
    308            document.body.removeChild(math);
    309        }
    310        return this._has_operator_spacing;
    311    },
    312 
    313    ensure_for_match_reftest: function(has_function) {
    314        if (!document.querySelector("link[rel='match']"))
    315            throw "This function must only be used for match reftest";
    316        // Add a little red square at the top left corner if the feature is not supported in order to make match reftest fail.
    317        if (!this[has_function]()) {
    318            document.body.insertAdjacentHTML("beforeend", "\
    319 <div style='width: 10px !important; height: 10px !important;\
    320            position: absolute !important;\
    321            left: 0 !important; top: 0 !important;\
    322            background: red !important; z-index: 1000 !important;'></div>");
    323        }
    324    }
    325 };