|
| 1 | +"use strict"; |
| 2 | +var assert = require('assert'); |
| 3 | +var texvcjs = require('../'); |
| 4 | + |
| 5 | +var fs = require('fs'); |
| 6 | +var path = require('path'); |
| 7 | + |
| 8 | +// set this variable to the path to your texvccheck binary for additional |
| 9 | +// sanity-checking against the ocaml texvccheck. |
| 10 | +var TEXVCBINARY=0; // "../../Math/texvccheck/texvccheck"; |
| 11 | + |
| 12 | +var tryocaml = function(input, output, done, fixDoubleSpacing) { |
| 13 | + if (!TEXVCBINARY) { return done(); } |
| 14 | + var cp = require('child_process'); |
| 15 | + cp.execFile(TEXVCBINARY, [input], { encoding: 'utf8' }, function(err,stdout,stderr) { |
| 16 | + if (err) { return done(err); } |
| 17 | + if (stderr) { return done(stderr); } |
| 18 | + if (fixDoubleSpacing) { stdout = stdout.replace(/ /g, ' '); } |
| 19 | + assert.equal(stdout, '+' + output); |
| 20 | + done(); |
| 21 | + }); |
| 22 | +}; |
| 23 | + |
| 24 | +var known_bad = Object.create(null); |
| 25 | +[ |
| 26 | + // Illegal TeX function: \fint |
| 27 | + "\\fint", |
| 28 | + |
| 29 | + // Illegal TeX function: \for |
| 30 | + "\\for every", |
| 31 | + |
| 32 | + // wikitext! |
| 33 | + "</nowiki> tag exists if that was the only help page you read. If you looked at [[Help:Math]] (also known as [[Help:Displaying a formula]], [[Help:Formula]] and a bunch of other names), the first thing it says is \"MediaWiki uses a subset of TeX markup\"; a bit later, under \"[[Help:Math#Syntax|Syntax]]\", it says \"Math markup goes inside <nowiki><math> ... ", |
| 34 | + |
| 35 | + // colors should be 0-1, not 0-255 |
| 36 | + "\\definecolor{gray}{RGB}{249,249,249}\\pagecolor{gray} g \\mapsto g\\circ h", |
| 37 | + |
| 38 | + // unicode literal: ≠ |
| 39 | + "\\frac{a}{b}, a, b \\in \\mathbb{Z}, b ≠ 0", |
| 40 | + |
| 41 | + // "Command \^ invalid in math mode" |
| 42 | + "\\gamma\\,\\pi\\,\\sec\\^2(\\pi\\,(p-\\tfrac{1}{2}))\\!", |
| 43 | + |
| 44 | + // html entity |
| 45 | + "\\mathbb{Q} \\big( \\sqrt{1 – p^2} \\big)", |
| 46 | + |
| 47 | + // unicode literal: ∈ |
| 48 | + "p_k ∈ J", |
| 49 | + |
| 50 | + // unicode literal: − |
| 51 | + "(r−k)!", |
| 52 | + |
| 53 | + // colors are 0-1 |
| 54 | + "\\definecolor{red}{RGB}{255,0,0}\\pagecolor{red}e^{i \\pi} + 1 = 0\\,\\!", |
| 55 | + |
| 56 | + // anomalous @ (but this is valid in math mode) |
| 57 | + "ckl@ckl", |
| 58 | + |
| 59 | + // unicode literal: × |
| 60 | + "u×v", |
| 61 | + |
| 62 | + // bad {} nesting |
| 63 | + "V_{\\text{in}(t)", |
| 64 | + |
| 65 | + // Illegal TeX function: \cdotP |
| 66 | + "\\left[\\begin{array}{c} L_R \\\\ L_G \\\\ L_B \\end{array}\\right]=\\mathbf{P^{-1}A^{-1}}\\left[\\begin{array}{ccc}R_w/R'_w & 0 & 0 \\\\ 0 & G_w/G'_w & 0 \\\\ 0 & 0 & B_w/B'_w\\end{array}\\right]\\mathbf{A\\cdotP}\\left[\\begin{array}{c}L_{R'} \\\\ L_{G'} \\\\ L_{B'} \\end{array}\\right]", |
| 67 | + |
| 68 | + // Illegal TeX function: \colour |
| 69 | + "\\colour{red}test", |
| 70 | + |
| 71 | + // unicode literal: ½ |
| 72 | + "½", |
| 73 | + |
| 74 | + // unicode literal: … |
| 75 | + "…", |
| 76 | + |
| 77 | + // Illegal TeX function: \y |
| 78 | + " \\y (s) ", |
| 79 | + |
| 80 | + // colors should be 0-1, not 0-255 |
| 81 | + "\\definecolor{orange}{RGB}{255,165,0}\\pagecolor{orange}z=re^{i\\phi}=x+iy \\,\\!", |
| 82 | + |
| 83 | + // should be \left\{ not \left{ |
| 84 | + "\\delta M_i^{-1} = - \\propto \\sum_{n=1}^N D_i \\left[ n \\right] \\left[ \\sum_{j \\in C \\left{i\\right} } F_{j i} \\left[ n - 1 \\right] + Fext_i \\left[ n^-1 \\right] \\right]", |
| 85 | + |
| 86 | + // Illegal TeX function: \sout |
| 87 | + "\\sout{4\\pi x}", |
| 88 | + |
| 89 | + // unicode literal: − |
| 90 | + "~\\sin^{−1} \\alpha", |
| 91 | + |
| 92 | + // wikitext |
| 93 | + "\"</nowiki> and <nowiki>\"", |
| 94 | + |
| 95 | + // unicode literal (?): \201 / \x81 |
| 96 | + "\\ x\x81'=ax+by+k_1", |
| 97 | + |
| 98 | + // wikitext |
| 99 | + "</nowiki></code> tag does not consistently italicize text which it encloses. For example, compare \"<math>Q = d", |
| 100 | + |
| 101 | + // unicode literal: ² |
| 102 | + "x²", |
| 103 | + |
| 104 | + // Illegal TeX function: \grdot |
| 105 | + "\\grdot", |
| 106 | + |
| 107 | + // Illegal TeX function: \setin (also missing "}") |
| 108 | + "\\mathbb{\\hat{C}}\\setminus \\overline{\\mathbb{D}} = { w\\setin", |
| 109 | + |
| 110 | + // unicode literal: − |
| 111 | + "x−y", |
| 112 | + |
| 113 | + // Illegal TeX function: \spacingcommand |
| 114 | + "\\scriptstyle\\spacingcommand ", |
| 115 | + |
| 116 | + // unicode literal: π |
| 117 | + "e^{iπ} = \\cos(π) + i\\sin(π) \\!", |
| 118 | + |
| 119 | + // unicode literal: α |
| 120 | + "sin 2α", |
| 121 | + |
| 122 | + // colors should be 0-1, not 0-255 |
| 123 | + "\\definecolor{orange}{RGB}{255,165,0}\\pagecolor{orange}e^{i \\pi} + 1 = 0\\,\\!", |
| 124 | + |
| 125 | + // unicode literal: ∈ |
| 126 | + "\\sum_{v=∈V}^{dv} i", |
| 127 | + |
| 128 | + // missing \right) |
| 129 | + "Q(x + \\alpha,y + \\beta) = \\sum_{i,j} a_{i,j} \\left( \\sum_u \\begin{pmatrix}i\\\\u\\end{pmatrix} x^u \\alpha^{i-u} \\right) \\left( \\sum_v", |
| 130 | + |
| 131 | + // missing \left) |
| 132 | + "\\begin{pmatrix}i\\\\v\\end{pmatrix} y^v \\beta^{j-v} \\right)", |
| 133 | + |
| 134 | + // unicode literal: ₃ |
| 135 | + "i₃", |
| 136 | + |
| 137 | + // unicode literal: ≠ |
| 138 | + "x ≠ 0", |
| 139 | + |
| 140 | + // unicode literals: α, →, β |
| 141 | + "((α → β) → α) → α", |
| 142 | + |
| 143 | + // unicode literal: − |
| 144 | + "(\\sin(\\alpha))^{−1}\\,", |
| 145 | + |
| 146 | + // wikitext |
| 147 | + "</nowiki>…<nowiki>", |
| 148 | + |
| 149 | + // not enough arguments to \frac |
| 150 | + "K_i = \\gamma^{L} _{i} * P_{i,Sat} \\frac{{P}}", |
| 151 | + |
| 152 | + // colors should be 0-1, not 0-255 |
| 153 | + "\\definecolor{gray}{RGB}{249,249,249}\\pagecolor{gray} g \\mapsto f\\circ g", |
| 154 | + |
| 155 | + // wikitext |
| 156 | + " it has broken spacing --> meters. LIGO should be able to detect gravitational waves as small as <math>h \\approx 5\\times 10^{-22}", |
| 157 | + |
| 158 | + // not enough arguments |
| 159 | + "\\binom", |
| 160 | + |
| 161 | + // unicode literal: − |
| 162 | + "\\text {E}=\\text {mgh}=0.1\\times980\\times10^{−2}=0.98\\text {erg}", |
| 163 | + |
| 164 | + // unicode literals: ⊈, Ō |
| 165 | + "⊈Ō", |
| 166 | +].forEach(function(s) { known_bad[s] = true; }); |
| 167 | + |
| 168 | +// mocha is too slow if we run these as 287,201 individual test cases. |
| 169 | +// run them in chunks in order to speed up reporting. |
| 170 | +var CHUNKSIZE = 1000; |
| 171 | + |
| 172 | +describe('All formulae from en-wiki:', function() { |
| 173 | + // read test cases |
| 174 | + var formulae = |
| 175 | + fs.readFileSync(path.join(__dirname, 'en-wiki-formulae.txt'), 'utf8'). |
| 176 | + split(/\n+/g); |
| 177 | + |
| 178 | + // group them into chunks |
| 179 | + var grouped = (function(arr, n) { |
| 180 | + var result = [], group = []; |
| 181 | + var seen = Object.create(null); |
| 182 | + arr.forEach(function(elem) { |
| 183 | + if (seen[elem]) { return; } else { seen[elem] = true; } |
| 184 | + group.push(elem); |
| 185 | + if (group.length >= n) { |
| 186 | + result.push(group); |
| 187 | + group = []; |
| 188 | + } |
| 189 | + }); |
| 190 | + result.push(group); |
| 191 | + return result; |
| 192 | + })(formulae, CHUNKSIZE); |
| 193 | + |
| 194 | + // create a mocha test case for each chunk |
| 195 | + grouped.forEach(function(group) { |
| 196 | + it(group[0] + ' ... ' + group[group.length-1], function() { |
| 197 | + group.forEach(function(f) { |
| 198 | + var result = texvcjs.check(f); |
| 199 | + var good = (result.status === '+'); |
| 200 | + if (known_bad[f]) { |
| 201 | + assert.ok(!good, f); |
| 202 | + } else { |
| 203 | + assert.ok(good, f); |
| 204 | + } |
| 205 | + }); |
| 206 | + }); |
| 207 | + }); |
| 208 | +}); |
0 commit comments