mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-07 20:28:38 +00:00
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:
@@ -511,7 +511,9 @@ var groupTypes = {
|
|||||||
|
|
||||||
// Vertical spacing
|
// Vertical spacing
|
||||||
var baselineskip = 12 * pt; // see size10.clo
|
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 arrayskip = arraystretch * baselineskip;
|
||||||
var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
|
var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
|
||||||
var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
|
var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
|
||||||
@@ -565,14 +567,19 @@ var groupTypes = {
|
|||||||
body[r] = outrow;
|
body[r] = outrow;
|
||||||
}
|
}
|
||||||
var offset = totalHeight / 2 + fontMetrics.metrics.axisHeight;
|
var offset = totalHeight / 2 + fontMetrics.metrics.axisHeight;
|
||||||
var colalign = group.value.colalign || [];
|
var coldescriptions = group.value.cols || [];
|
||||||
var cols = [];
|
var cols = [];
|
||||||
var colsep;
|
var colsep;
|
||||||
for (c = 0; c < nc; ++c) {
|
for (c = 0; c < nc; ++c) {
|
||||||
|
var coldescr = coldescriptions[c] || {};
|
||||||
|
var sepwidth;
|
||||||
if (c > 0 || group.value.hskipBeforeAndAfter) {
|
if (c > 0 || group.value.hskipBeforeAndAfter) {
|
||||||
colsep = makeSpan(["arraycolsep"], []);
|
sepwidth = utils.deflt(coldescr.pregap, arraycolsep);
|
||||||
colsep.style.width = arraycolsep + "em";
|
if (sepwidth !== 0) {
|
||||||
cols.push(colsep);
|
colsep = makeSpan(["arraycolsep"], []);
|
||||||
|
colsep.style.width = sepwidth + "em";
|
||||||
|
cols.push(colsep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var col = [];
|
var col = [];
|
||||||
for (r = 0; r < nr; ++r) {
|
for (r = 0; r < nr; ++r) {
|
||||||
@@ -588,13 +595,16 @@ var groupTypes = {
|
|||||||
}
|
}
|
||||||
col = buildCommon.makeVList(col, "individualShift", null, options);
|
col = buildCommon.makeVList(col, "individualShift", null, options);
|
||||||
col = makeSpan(
|
col = makeSpan(
|
||||||
["col-align-" + (colalign[c] || "c")],
|
["col-align-" + (coldescr.align || "c")],
|
||||||
[col]);
|
[col]);
|
||||||
cols.push(col);
|
cols.push(col);
|
||||||
if (c < nc - 1 || group.value.hskipBeforeAndAfter) {
|
if (c < nc - 1 || group.value.hskipBeforeAndAfter) {
|
||||||
colsep = makeSpan(["arraycolsep"], []);
|
sepwidth = utils.deflt(coldescr.postgap, arraycolsep);
|
||||||
colsep.style.width = arraycolsep + "em";
|
if (sepwidth !== 0) {
|
||||||
cols.push(colsep);
|
colsep = makeSpan(["arraycolsep"], []);
|
||||||
|
colsep.style.width = sepwidth + "em";
|
||||||
|
cols.push(colsep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
body = makeSpan(["mtable"], cols);
|
body = makeSpan(["mtable"], cols);
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
var fontMetrics = require("./fontMetrics");
|
||||||
var parseData = require("./parseData");
|
var parseData = require("./parseData");
|
||||||
var ParseError = require("./ParseError");
|
var ParseError = require("./ParseError");
|
||||||
|
|
||||||
@@ -66,10 +67,12 @@ var environmentDefinitions = [
|
|||||||
var parser = this;
|
var parser = this;
|
||||||
// Currently only supports alignment, no separators like | yet.
|
// Currently only supports alignment, no separators like | yet.
|
||||||
colalign = colalign.value.map ? colalign.value : [colalign];
|
colalign = colalign.value.map ? colalign.value : [colalign];
|
||||||
colalign = colalign.map(function(node) {
|
var cols = colalign.map(function(node) {
|
||||||
var ca = node.value;
|
var ca = node.value;
|
||||||
if ("lcr".indexOf(ca) !== -1) {
|
if ("lcr".indexOf(ca) !== -1) {
|
||||||
return ca;
|
return {
|
||||||
|
align: ca
|
||||||
|
};
|
||||||
}
|
}
|
||||||
throw new ParseError(
|
throw new ParseError(
|
||||||
"Unknown column alignment: " + node.value,
|
"Unknown column alignment: " + node.value,
|
||||||
@@ -77,7 +80,7 @@ var environmentDefinitions = [
|
|||||||
});
|
});
|
||||||
var res = {
|
var res = {
|
||||||
type: "array",
|
type: "array",
|
||||||
colalign: colalign,
|
cols: cols,
|
||||||
hskipBeforeAndAfter: true // \@preamble in lttab.dtx
|
hskipBeforeAndAfter: true // \@preamble in lttab.dtx
|
||||||
};
|
};
|
||||||
res = parseArray(parser, pos, mode, res);
|
res = parseArray(parser, pos, mode, res);
|
||||||
@@ -111,8 +114,36 @@ var environmentDefinitions = [
|
|||||||
}
|
}
|
||||||
return res;
|
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() {
|
module.exports = (function() {
|
||||||
|
@@ -31,6 +31,13 @@ var contains = function(list, elem) {
|
|||||||
return indexOf(list, elem) !== -1;
|
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
|
// hyphenate and escape adapted from Facebook's React under Apache 2 license
|
||||||
|
|
||||||
var uppercase = /([A-Z])/g;
|
var uppercase = /([A-Z])/g;
|
||||||
@@ -89,6 +96,7 @@ function clearNode(node) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
contains: contains,
|
contains: contains,
|
||||||
|
deflt: deflt,
|
||||||
escape: escape,
|
escape: escape,
|
||||||
hyphenate: hyphenate,
|
hyphenate: hyphenate,
|
||||||
indexOf: indexOf,
|
indexOf: indexOf,
|
||||||
|
@@ -1310,7 +1310,17 @@ describe("An array environment", function() {
|
|||||||
it("should accept a single alignment character", function() {
|
it("should accept a single alignment character", function() {
|
||||||
var parse = getParsed("\\begin{array}r1\\\\20\\end{array}");
|
var parse = getParsed("\\begin{array}r1\\\\20\\end{array}");
|
||||||
expect(parse[0].type).toBe("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();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
BIN
test/screenshotter/images/Cases-firefox.png
Normal file
BIN
test/screenshotter/images/Cases-firefox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@@ -4,6 +4,7 @@
|
|||||||
"Baseline": "http://localhost:7936/test/screenshotter/test.html?m=a+b-c\\cdot d/e",
|
"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",
|
"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}",
|
"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}",
|
"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}",
|
"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",
|
"DelimiterSizing": "http://localhost:7936/test/screenshotter/test.html?m=\\bigl\\uparrow\\Bigl\\downarrow\\biggl\\updownarrow\\Biggl\\Uparrow\\Biggr\\Downarrow\\biggr\\langle\\Bigr\\}\\bigr\\rfloor",
|
||||||
|
Reference in New Issue
Block a user