Implement cases environment

See issue #278.  Although the official definition makes use of @{…}
notation, we use custom spacing instead, since that seems easier for now.
This commit is contained in:
Martin von Gagern 2015-06-30 09:41:03 +02:00
parent 7f1b53cbfd
commit 758bdba31e
6 changed files with 74 additions and 14 deletions

View File

@ -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);

View File

@ -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() {

View File

@ -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,

View File

@ -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();
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -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",