Switch Screenshotter data from JSON to YAML

Escaping TeX in JSON as query strings is a pain: you have to double all the
\\, you have to escape the & and the #, you can't easily include line breaks
for readability, and so on.  YAML solves most of these problems for most of
the situations.  Now each test case can be structured, while simple test
cases only consist of a line of verbatim TeX code, with no escaping.

The most troublesome items remaining are lines starting in { since in YAML
these would denote inline mapping types. We use block notation for these.
This commit is contained in:
Martin von Gagern 2015-07-15 16:50:47 +02:00
parent a3031af307
commit fb403fa9eb
7 changed files with 137 additions and 72 deletions

View File

@ -8,7 +8,7 @@ var net = require("net");
var selenium = require("selenium-webdriver"); var selenium = require("selenium-webdriver");
var app = require("../../server"); var app = require("../../server");
var data = require("../../test/screenshotter/ss_data.json"); var data = require("../../test/screenshotter/ss_data");
var dstDir = path.normalize( var dstDir = path.normalize(
path.join(__dirname, "..", "..", "test", "screenshotter", "images")); path.join(__dirname, "..", "..", "test", "screenshotter", "images"));
@ -130,8 +130,6 @@ if (seleniumURL) {
console.log("Selenium driver in local session"); console.log("Selenium driver in local session");
} }
var toStrip = "http://localhost:7936/"; // remove this from testcase URLs
process.nextTick(startServer); process.nextTick(startServer);
var attempts = 0; var attempts = 0;
@ -248,12 +246,12 @@ function takeScreenshots() {
} }
function takeScreenshot(key) { function takeScreenshot(key) {
var url = data[key]; var itm = data[key];
if (!url) { if (!itm) {
console.error("Test case " + key + " not known!"); console.error("Test case " + key + " not known!");
return; return;
} }
url = katexURL + url.substr(toStrip.length); var url = katexURL + "test/screenshotter/test.html?" + itm.query;
driver.get(url); driver.get(url);
driver.takeScreenshot().then(function haveScreenshot(img) { driver.takeScreenshot().then(function haveScreenshot(img) {
img = imageDimensions(img); img = imageDimensions(img);

View File

@ -1,6 +1,5 @@
"use strict"; "use strict";
var querystring = require("querystring");
var childProcess = require("child_process"); var childProcess = require("child_process");
var fs = require("fs"); var fs = require("fs");
var path = require("path"); var path = require("path");
@ -16,18 +15,12 @@ var readFile = Q.denodeify(fs.readFile);
var writeFile = Q.denodeify(fs.writeFile); var writeFile = Q.denodeify(fs.writeFile);
var mkdir = Q.denodeify(fs.mkdir); var mkdir = Q.denodeify(fs.mkdir);
// ignore some tests, since they contain commands not supported by LaTeX
var blacklist = {
Colors: "Color handling differs",
DeepFontSizing: "\\Huge inside \\dfrac doesn't work for some reason",
KaTeX: "Custom command, doesn't exist in LaTeX"
};
var todo; var todo;
if (process.argv.length > 2) { if (process.argv.length > 2) {
todo = process.argv.slice(2); todo = process.argv.slice(2);
} else { } else {
todo = Object.keys(data).filter(function(key) { todo = Object.keys(data).filter(function(key) {
return !blacklist[key]; return !data[key].nolatex;
}); });
} }
@ -63,22 +56,16 @@ Q.all([
// Process a single test case: rasterize, then create diff // Process a single test case: rasterize, then create diff
function processTestCase(key) { function processTestCase(key) {
if (blacklist[key]) { var itm = data[key];
return; var tex = "$" + itm.tex + "$";
if (itm.display) {
tex = "\\[" + itm.tex + "\\]";
} }
var url = data[key]; if (itm.pre) {
var query = url.replace(/^.*?\?/, ""); // extract query string tex = itm.pre.replace("<br>", "\\\\") + tex;
query = query.replace(/\+/g, "%2B"); // plus doesn't mean space here
query = querystring.parse(query);
var tex = "$" + query.m + "$";
if (query.display) {
tex = "$$" + query.m + "$$";
} }
if (query.pre) { if (itm.post) {
tex = query.pre.replace("<br>", "\\\\") + tex; tex = tex + itm.post.replace("<br>", "\\\\");
}
if (query.post) {
tex = tex + query.post.replace("<br>", "\\\\");
} }
tex = template.replace(/\$.*\$/, tex.replace(/\$/g, "$$$$")); tex = template.replace(/\$.*\$/, tex.replace(/\$/g, "$$$$"));
var texFile = path.join(tmpDir, key + ".tex"); var texFile = path.join(tmpDir, key + ".tex");

View File

@ -18,10 +18,11 @@
"clean-css": "~2.2.15", "clean-css": "~2.2.15",
"express": "~3.3.3", "express": "~3.3.3",
"jasmine-node": "2.0.0-beta4", "jasmine-node": "2.0.0-beta4",
"js-yaml": "^3.3.1",
"jshint": "^2.5.6", "jshint": "^2.5.6",
"less": "~1.7.5", "less": "~1.7.5",
"selenium-webdriver": "^2.46.1",
"nomnom": "^1.8.1", "nomnom": "^1.8.1",
"selenium-webdriver": "^2.46.1",
"uglify-js": "~2.4.15" "uglify-js": "~2.4.15"
}, },
"bin": "cli.js", "bin": "cli.js",

View File

@ -0,0 +1,23 @@
/**
* Parse and polish the screenshotter data in ss_data.yaml.
*
* This module is responsible for reading the file ss_data.yaml,
* unify syntactic variations (like string vs. dict as test case body)
* and provide common functionality (like a query string encoded version).
* The export of this module is simply a dictionary of test cases.
*/
var fs = require("fs");
var jsyaml = require("js-yaml");
var querystring = require("querystring");
var dict = fs.readFileSync(require.resolve("./ss_data.yaml"));
dict = jsyaml.safeLoad(dict);
for (var key in dict) {
var itm = dict[key];
if (typeof itm === "string") {
itm = dict[key] = { tex: itm };
}
itm.query = querystring.stringify(itm);
}
module.exports = dict;

View File

@ -1,41 +0,0 @@
{
"Accents": "http://localhost:7936/test/screenshotter/test.html?m=\\vec{A}\\vec{x}\\vec x^2\\vec{x}_2^2\\vec{A}^2\\vec{xA}^2",
"Arrays": "http://localhost:7936/test/screenshotter/test.html?m=\\left(\\begin{array}{rlc}1%262%263\\\\1+1%262+1%263+1\\cr1\\over2%26\\scriptstyle 1/2%26\\frac12\\\\[1ex]\\begin{pmatrix}x\\\\y\\end{pmatrix}%260%26\\begin{vmatrix}a%26b\\\\c%26d\\end{vmatrix}\\end{array}\\right]",
"ArrayType": "http://localhost:7936/test/screenshotter/test.html?m=1\\begin{array}{c}2\\\\3\\end{array}4",
"Baseline": "http://localhost:7936/test/screenshotter/test.html?m=a+b-c\\cdot d/e",
"BasicTest": "http://localhost:7936/test/screenshotter/test.html?m=a",
"BinomTest": "http://localhost:7936/test/screenshotter/test.html?m=\\dbinom{a}{b}\\tbinom{a}{b}^{\\binom{a}{b}+17}",
"Cases": "http://localhost:7936/test/screenshotter/test.html?m=f(a,b)=\\begin{cases}a+1%26\\text{if }b\\text{ is odd}\\\\a%26\\text{if }b=0\\\\a-1%26\\text{otherwise}\\end{cases}",
"Colors": "http://localhost:7936/test/screenshotter/test.html?m=\\blue{a}\\color{%230f0}{b}\\color{red}{c}",
"DeepFontSizing": "http://localhost:7936/test/screenshotter/test.html?m=a^{\\big| x^{\\big(}}_{\\Big\\uparrow} + i^{i^{\\Huge x}_y}_{\\Huge z} + \\dfrac{\\Huge x}{y}",
"DelimiterSizing": "http://localhost:7936/test/screenshotter/test.html?m=\\bigl\\uparrow\\Bigl\\downarrow\\biggl\\updownarrow\\Biggl\\Uparrow\\Biggr\\Downarrow\\biggr\\langle\\Bigr\\}\\bigr\\rfloor",
"DisplayMode": "http://localhost:7936/test/screenshotter/test.html?m=\\sum_{i=0}^\\infty \\frac{1}{i}&pre=pre&post=post&display=1",
"DisplayStyle": "http://localhost:7936/test/screenshotter/test.html?m={\\displaystyle\\sqrt{x}}{\\sqrt{x}}{\\displaystyle \\frac12}{\\frac12}{\\displaystyle x^1_2}{x^1_2}",
"Exponents": "http://localhost:7936/test/screenshotter/test.html?m=a^{a^a_a}_{a^a_a}",
"FractionTest": "http://localhost:7936/test/screenshotter/test.html?m=\\dfrac{a}{b}\\frac{a}{b}\\tfrac{a}{b}\\;-\\dfrac12\\;1\\tfrac12",
"Functions": "http://localhost:7936/test/screenshotter/test.html?m=\\sin\\cos\\tan\\ln\\log",
"GreekLetters": "http://localhost:7936/test/screenshotter/test.html?m=\\alpha\\beta\\gamma\\omega",
"KaTeX": "http://localhost:7936/test/screenshotter/test.html?m=\\KaTeX",
"Lap": "http://localhost:7936/test/screenshotter/test.html?m=ab\\llap{f}cd\\rlap{g}h",
"LeftRight": "http://localhost:7936/test/screenshotter/test.html?m=\\left( x^2 \\right) \\left\\{ x^{x^{x^{x^x}}} \\right.",
"LeftRightListStyling": "http://localhost:7936/test/screenshotter/test.html?m=a+\\left(x+y\\right)-x",
"LeftRightStyleSizing": "http://localhost:7936/test/screenshotter/test.html?m=+\\left\\{\\rule{0.1em}{1em}\\right.x^{+\\left\\{\\rule{0.1em}{1em}\\right.x^{+\\left\\{\\rule{0.1em}{1em}\\right.}}",
"NestedFractions": "http://localhost:7936/test/screenshotter/test.html?m=\\dfrac{\\frac{a}{b}}{\\frac{c}{d}}\\dfrac{\\dfrac{a}{b}}{\\dfrac{c}{d}}\\frac{\\frac{a}{b}}{\\frac{c}{d}}",
"NullDelimiterInteraction": "http://localhost:7936/test/screenshotter/test.html?m=a \\bigl. + 2 \\quad \\left. + a \\right)",
"OpLimits": "http://localhost:7936/test/screenshotter/test.html?m={\\sin_2^2 \\lim_2^2 \\int_2^2 \\sum_2^2}{\\displaystyle \\lim_2^2 \\int_2^2 \\intop_2^2 \\sum_2^2}",
"Overline": "http://localhost:7936/test/screenshotter/test.html?m=\\overline{x}\\overline{x}\\overline{x^{x^{x^x}}} \\blue{\\overline{y}}",
"Phantom": "http://localhost:7936/test/screenshotter/test.html?m=\\dfrac{1+\\phantom{x^{\\blue{2}}} = x}{1+x^{\\blue{2}} = x}",
"PrimeSpacing": "http://localhost:7936/test/screenshotter/test.html?m=f'+f_2'+f^{f'}",
"RlapBug": "http://localhost:7936/test/screenshotter/test.html?m=\\frac{\\rlap{x}}{2}",
"Rule": "http://localhost:7936/test/screenshotter/test.html?m=\\rule{1em}{0.5em}\\rule{1ex}{2ex}\\rule{1em}{1ex}\\rule{1em}{0.431ex}",
"SizingBaseline": "http://localhost:7936/test/screenshotter/test.html?m={\\tiny a+b}a+b{\\Huge a+b}&pre=x&post=M",
"Sizing": "http://localhost:7936/test/screenshotter/test.html?m={\\Huge x}{\\LARGE y}{\\normalsize z}{\\scriptsize w}",
"Spacing": "http://localhost:7936/test/screenshotter/test.html?m=^3+[-1][1-1]1=1(=1)\\lvert a\\rvert~b",
"Sqrt": "http://localhost:7936/test/screenshotter/test.html?m=\\sqrt{\\sqrt{\\sqrt{x}}}_{\\sqrt{\\sqrt{x}}}^{\\sqrt{\\sqrt{\\sqrt{x}}}^{\\sqrt{\\sqrt{\\sqrt{x}}}}}",
"SqrtRoot": "http://localhost:7936/test/screenshotter/test.html?m=1+\\sqrt[3]{2}+\\sqrt[1923^234]{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^2}}}}}}}}}}}",
"SupSubCharacterBox": "http://localhost:7936/test/screenshotter/test.html?m=a_2f_2{f}_2{aa}_2{af}_2",
"SupSubHorizSpacing": "http://localhost:7936/test/screenshotter/test.html?m=x^{x^{x}}\\Big|x_{x_{x_{x_{x}}}}\\bigg|x^{x^{x_{x_{x_{x_{x}}}}}}\\bigg|",
"SupSubOffsets": "http://localhost:7936/test/screenshotter/test.html?m=\\displaystyle \\int_{2+3}x f^{2+3}+3\\lim_{2+3+4+5}f",
"Text": "http://localhost:7936/test/screenshotter/test.html?m=\\frac{a}{b}\\text{c~ {ab} \\ e}+fg",
"VerticalSpacing": "http://localhost:7936/test/screenshotter/test.html?pre=potato<br>blah&post=<br>moo&m=x^{\\Huge y}z"
}

View File

@ -0,0 +1,97 @@
# List of test cases for which we create screenshots and other documents.
# Each value in the top level dictionary is either a string or a dict
# which may contain the following keys:
# - tex: the KaTeX input string
# - pre: some HTML to insert before the KaTeX content
# - post: some HTML to insert after the KaTeX content
# - display: set this to 1 in order to use display style
#
# Note that YAML will treat a value starting in { as a flow mapping.
# To avoid that, either enclose the value in '…' or use a block scalar style,
# writing | (or >) as the first symbol of the value and then continuing
# on the next line. See http://www.yaml.org/ for syntax details.
Accents: \vec{A}\vec{x}\vec x^2\vec{x}_2^2\vec{A}^2\vec{xA}^2
Arrays: |
\left(\begin{array}{rlc}
1&2&3\\
1+1&2+1&3+1\cr1\over2&\scriptstyle 1/2&\frac12\\[1ex]
\begin{pmatrix}x\\y\end{pmatrix}&0&\begin{vmatrix}a&b\\c&d\end{vmatrix}
\end{array}\right]
ArrayType: 1\begin{array}{c}2\\3\end{array}4
Baseline: a+b-c\cdot d/e
BasicTest: a
BinomTest: \dbinom{a}{b}\tbinom{a}{b}^{\binom{a}{b}+17}
Cases: |
f(a,b)=\begin{cases}
a+1&\text{if }b\text{ is odd} \\
a&\text{if }b=0 \\
a-1&\text{otherwise}
\end{cases}
Colors:
tex: \blue{a}\color{#0f0}{b}\color{red}{c}
nolatex: different syntax and different scope
DeepFontSizing:
tex: |
a^{\big| x^{\big(}}_{\Big\uparrow} +
i^{i^{\Huge x}_y}_{\Huge z} +
\dfrac{\Huge x}{y}
nolatex: \Huge inside \dfrac doesn't work, needs an extra {…}
DelimiterSizing: |
\bigl\uparrow\Bigl\downarrow\biggl\updownarrow
\Biggl\Uparrow\Biggr\Downarrow\biggr\langle\Bigr\}\bigr\rfloor
DisplayMode:
tex: \sum_{i=0}^\infty \frac{1}{i}
pre: pre
post: post
display: 1
DisplayStyle: |
{\displaystyle\sqrt{x}}{\sqrt{x}}
{\displaystyle \frac12}{\frac12}{\displaystyle x^1_2}{x^1_2}
Exponents: a^{a^a_a}_{a^a_a}
FractionTest: \dfrac{a}{b}\frac{a}{b}\tfrac{a}{b}\;-\dfrac12\;1\tfrac12
Functions: \sin\cos\tan\ln\log
GreekLetters: \alpha\beta\gamma\omega
KaTeX:
tex: \KaTeX
nolatex: There is no LaTeX command for this (yet)
Lap: ab\llap{f}cd\rlap{g}h
LeftRight: \left( x^2 \right) \left\{ x^{x^{x^{x^x}}} \right.
LeftRightListStyling: a+\left(x+y\right)-x
LeftRightStyleSizing: |
+\left\{\rule{0.1em}{1em}\right.
x^{+\left\{\rule{0.1em}{1em}\right.
x^{+\left\{\rule{0.1em}{1em}\right.}}
NestedFractions: |
\dfrac{\frac{a}{b}}{\frac{c}{d}}\dfrac{\dfrac{a}{b}}
{\dfrac{c}{d}}\frac{\frac{a}{b}}{\frac{c}{d}}
NullDelimiterInteraction: a \bigl. + 2 \quad \left. + a \right)
OpLimits: |
{\sin_2^2 \lim_2^2 \int_2^2 \sum_2^2}
{\displaystyle \lim_2^2 \int_2^2 \intop_2^2 \sum_2^2}
Overline: \overline{x}\overline{x}\overline{x^{x^{x^x}}} \blue{\overline{y}}
Phantom: \dfrac{1+\phantom{x^{\blue{2}}} = x}{1+x^{\blue{2}} = x}
PrimeSpacing: f'+f_2'+f^{f'}
RlapBug: \frac{\rlap{x}}{2}
Rule: \rule{1em}{0.5em}\rule{1ex}{2ex}\rule{1em}{1ex}\rule{1em}{0.431ex}
SizingBaseline:
tex: '{\tiny a+b}a+b{\Huge a+b}'
pre: x
post: M
Sizing: |
{\Huge x}{\LARGE y}{\normalsize z}{\scriptsize w}
Spacing: ^3+[-1][1-1]1=1(=1)\lvert a\rvert~b
Sqrt: |
\sqrt{\sqrt{\sqrt{x}}}_{\sqrt{\sqrt{x}}}^{\sqrt{\sqrt{\sqrt{x}}}
^{\sqrt{\sqrt{\sqrt{x}}}}}
SqrtRoot: |
1+\sqrt[3]{2}+\sqrt[1923^234]{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^{2^2}}}}}}}}}}}
SupSubCharacterBox: a_2f_2{f}_2{aa}_2{af}_2
SupSubHorizSpacing: |
x^{x^{x}}\Big|x_{x_{x_{x_{x}}}}\bigg|x^{x^{x_{x_{x_{x_{x}}}}}}\bigg|
SupSubOffsets: \displaystyle \int_{2+3}x f^{2+3}+3\lim_{2+3+4+5}f
Text: \frac{a}{b}\text{c~ {ab} \ e}+fg
VerticalSpacing:
pre: potato<br>blah
tex: x^{\Huge y}z
post: <br>moo

View File

@ -1,7 +1,7 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title>Huxley test</title> <title>Screenshotter test</title>
<script src="/katex.js" type="text/javascript"></script> <script src="/katex.js" type="text/javascript"></script>
<link href="/katex.css" rel="stylesheet" type="text/css"> <link href="/katex.css" rel="stylesheet" type="text/css">
<style type="text/css"> <style type="text/css">
@ -25,7 +25,7 @@
query[match[1]] = decodeURIComponent(match[2]); query[match[1]] = decodeURIComponent(match[2]);
} }
var mathNode = document.getElementById("math"); var mathNode = document.getElementById("math");
katex.render(query["m"], mathNode, { katex.render(query["tex"], mathNode, {
displayMode: !!query["display"] displayMode: !!query["display"]
}); });
document.getElementById("pre").innerHTML = query["pre"] || ""; document.getElementById("pre").innerHTML = query["pre"] || "";