diff --git a/src/buildHTML.js b/src/buildHTML.js index d34ac6a..759c319 100644 --- a/src/buildHTML.js +++ b/src/buildHTML.js @@ -511,7 +511,9 @@ var groupTypes = { // Vertical spacing var baselineskip = 12 * pt; // see size10.clo - var arraystretch = 1; // factor, see lttab.dtx + // Default \arraystretch from lttab.dtx + // TODO(gagern): may get redefined once we have user-defined macros + var arraystretch = utils.deflt(group.value.arraystretch, 1); var arrayskip = arraystretch * baselineskip; var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx @@ -565,14 +567,19 @@ var groupTypes = { body[r] = outrow; } var offset = totalHeight / 2 + fontMetrics.metrics.axisHeight; - var colalign = group.value.colalign || []; + var coldescriptions = group.value.cols || []; var cols = []; var colsep; for (c = 0; c < nc; ++c) { + var coldescr = coldescriptions[c] || {}; + var sepwidth; if (c > 0 || group.value.hskipBeforeAndAfter) { - colsep = makeSpan(["arraycolsep"], []); - colsep.style.width = arraycolsep + "em"; - cols.push(colsep); + sepwidth = utils.deflt(coldescr.pregap, arraycolsep); + if (sepwidth !== 0) { + colsep = makeSpan(["arraycolsep"], []); + colsep.style.width = sepwidth + "em"; + cols.push(colsep); + } } var col = []; for (r = 0; r < nr; ++r) { @@ -588,13 +595,16 @@ var groupTypes = { } col = buildCommon.makeVList(col, "individualShift", null, options); col = makeSpan( - ["col-align-" + (colalign[c] || "c")], + ["col-align-" + (coldescr.align || "c")], [col]); cols.push(col); if (c < nc - 1 || group.value.hskipBeforeAndAfter) { - colsep = makeSpan(["arraycolsep"], []); - colsep.style.width = arraycolsep + "em"; - cols.push(colsep); + sepwidth = utils.deflt(coldescr.postgap, arraycolsep); + if (sepwidth !== 0) { + colsep = makeSpan(["arraycolsep"], []); + colsep.style.width = sepwidth + "em"; + cols.push(colsep); + } } } body = makeSpan(["mtable"], cols); diff --git a/src/environments.js b/src/environments.js index 9da6a22..ba007d8 100644 --- a/src/environments.js +++ b/src/environments.js @@ -1,3 +1,4 @@ +var fontMetrics = require("./fontMetrics"); var parseData = require("./parseData"); var ParseError = require("./ParseError"); @@ -66,10 +67,12 @@ var environmentDefinitions = [ var parser = this; // Currently only supports alignment, no separators like | yet. colalign = colalign.value.map ? colalign.value : [colalign]; - colalign = colalign.map(function(node) { + var cols = colalign.map(function(node) { var ca = node.value; if ("lcr".indexOf(ca) !== -1) { - return ca; + return { + align: ca + }; } throw new ParseError( "Unknown column alignment: " + node.value, @@ -77,7 +80,7 @@ var environmentDefinitions = [ }); var res = { type: "array", - colalign: colalign, + cols: cols, hskipBeforeAndAfter: true // \@preamble in lttab.dtx }; res = parseArray(parser, pos, mode, res); @@ -111,8 +114,36 @@ var environmentDefinitions = [ } return res; } - } + }, + // A cases environment (in amsmath.sty) is almost equivalent to + // \def\arraystretch{1.2}% + // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right. + { + names: ["cases"], + handler: function(pos, mode, envName) { + var res = { + type: "array", + arraystretch: 1.2, + cols: [{ + align: "l", + pregap: 0, + postgap: fontMetrics.metrics.quad + }, { + align: "l", + pregap: 0, + postgap: 0 + }] + }; + res = parseArray(this, pos, mode, res); + res.result = new ParseNode("leftright", { + body: [res.result], + left: "\\{", + right: "." + }, mode); + return res; + } + } ]; module.exports = (function() { diff --git a/src/utils.js b/src/utils.js index 9b9bf71..078bef1 100644 --- a/src/utils.js +++ b/src/utils.js @@ -31,6 +31,13 @@ var contains = function(list, elem) { return indexOf(list, elem) !== -1; }; +/** + * Provide a default value if a setting is undefined + */ +var deflt = function(setting, defaultIfUndefined) { + return setting === undefined ? defaultIfUndefined : setting; +}; + // hyphenate and escape adapted from Facebook's React under Apache 2 license var uppercase = /([A-Z])/g; @@ -89,6 +96,7 @@ function clearNode(node) { module.exports = { contains: contains, + deflt: deflt, escape: escape, hyphenate: hyphenate, indexOf: indexOf, diff --git a/test/katex-spec.js b/test/katex-spec.js index abfc2a6..36b4f91 100644 --- a/test/katex-spec.js +++ b/test/katex-spec.js @@ -1310,7 +1310,17 @@ describe("An array environment", function() { it("should accept a single alignment character", function() { var parse = getParsed("\\begin{array}r1\\\\20\\end{array}"); expect(parse[0].type).toBe("array"); - expect(parse[0].value.colalign).toEqual(["r"]); + expect(parse[0].value.cols).toEqual([{align:"r"}]); + }); + +}); + +describe("A cases environment", function() { + + it("should parse its input", function() { + expect("f(a,b)=\\begin{cases}a+1&\\text{if }b\\text{ is odd}\\\\" + + "a&\\text{if }b=0\\\\a-1&\\text{otherwise}\\end{cases}") + .toParse(); }); }); diff --git a/test/screenshotter/images/Cases-firefox.png b/test/screenshotter/images/Cases-firefox.png new file mode 100644 index 0000000..2718f37 Binary files /dev/null and b/test/screenshotter/images/Cases-firefox.png differ diff --git a/test/screenshotter/ss_data.json b/test/screenshotter/ss_data.json index 9cac1ba..e3e2148 100644 --- a/test/screenshotter/ss_data.json +++ b/test/screenshotter/ss_data.json @@ -4,6 +4,7 @@ "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",