mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-07 20:28:38 +00:00
Implements the alignedat environment for flexible math spacing (#930)
* Implements the alignat environment for flexible math spacing * Renames alignat[*] to alignedat and factors out duplicate code of aligned and alignedat as alignedHandler * Adds aligned at to screenshotter * alignedat screenshots * Implements the alignat environment for flexible math spacing * Renames alignat[*] to alignedat and factors out duplicate code of aligned and alignedat as alignedHandler * Adds aligned at to screenshotter * alignedat screenshots * fix style nit * fix lint
This commit is contained in:
committed by
Kevin Barabash
parent
3e344535ff
commit
1a640a465e
@@ -276,6 +276,76 @@ const mathmlBuilder = function(group, options) {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Convinient function for aligned and alignedat environments.
|
||||||
|
const alignedHandler = function(context, args) {
|
||||||
|
let res = {
|
||||||
|
type: "array",
|
||||||
|
cols: [],
|
||||||
|
addJot: true,
|
||||||
|
};
|
||||||
|
res = parseArray(context.parser, res, "display");
|
||||||
|
|
||||||
|
// Determining number of columns.
|
||||||
|
// 1. If the first argument is given, we use it as a number of columns,
|
||||||
|
// and makes sure that each row doesn't exceed that number.
|
||||||
|
// 2. Otherwise, just count number of columns = maximum number
|
||||||
|
// of cells in each row ("aligned" mode -- isAligned will be true).
|
||||||
|
//
|
||||||
|
// At the same time, prepend empty group {} at beginning of every second
|
||||||
|
// cell in each row (starting with second cell) so that operators become
|
||||||
|
// binary. This behavior is implemented in amsmath's \start@aligned.
|
||||||
|
let numMaths;
|
||||||
|
let numCols = 0;
|
||||||
|
const emptyGroup = new ParseNode("ordgroup", [], context.mode);
|
||||||
|
if (args[0] && args[0].value) {
|
||||||
|
let arg0 = "";
|
||||||
|
for (let i = 0; i < args[0].value.length; i++) {
|
||||||
|
arg0 += args[0].value[i].value;
|
||||||
|
}
|
||||||
|
numMaths = Number(arg0);
|
||||||
|
numCols = numMaths * 2;
|
||||||
|
}
|
||||||
|
const isAligned = !numCols;
|
||||||
|
res.value.body.forEach(function(row) {
|
||||||
|
for (let i = 1; i < row.length; i += 2) {
|
||||||
|
// Modify ordgroup node within styling node
|
||||||
|
const ordgroup = row[i].value.value[0];
|
||||||
|
ordgroup.value.unshift(emptyGroup);
|
||||||
|
}
|
||||||
|
if (!isAligned) { // Case 1
|
||||||
|
const curMaths = row.length / 2;
|
||||||
|
if (numMaths < curMaths) {
|
||||||
|
throw new ParseError(
|
||||||
|
"Too many math in a row: " +
|
||||||
|
`expected ${numMaths}, but got ${curMaths}`,
|
||||||
|
row);
|
||||||
|
}
|
||||||
|
} else if (numCols < row.length) { // Case 2
|
||||||
|
numCols = row.length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Adjusting alignment.
|
||||||
|
// In aligned mode, we add one \qquad between columns;
|
||||||
|
// otherwise we add nothing.
|
||||||
|
for (let i = 0; i < numCols; ++i) {
|
||||||
|
let align = "r";
|
||||||
|
let pregap = 0;
|
||||||
|
if (i % 2 === 1) {
|
||||||
|
align = "l";
|
||||||
|
} else if (i > 0 && isAligned) { // "aligned" mode.
|
||||||
|
pregap = 1; // add one \quad
|
||||||
|
}
|
||||||
|
res.value.cols[i] = {
|
||||||
|
type: "align",
|
||||||
|
align: align,
|
||||||
|
pregap: pregap,
|
||||||
|
postgap: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
|
// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
|
||||||
// is part of the source2e.pdf file of LaTeX2e source documentation.
|
// is part of the source2e.pdf file of LaTeX2e source documentation.
|
||||||
// {darray} is an {array} environment where cells are set in \displaystyle,
|
// {darray} is an {array} environment where cells are set in \displaystyle,
|
||||||
@@ -416,46 +486,7 @@ defineEnvironment({
|
|||||||
props: {
|
props: {
|
||||||
numArgs: 0,
|
numArgs: 0,
|
||||||
},
|
},
|
||||||
handler: function(context) {
|
handler: alignedHandler,
|
||||||
let res = {
|
|
||||||
type: "array",
|
|
||||||
cols: [],
|
|
||||||
addJot: true,
|
|
||||||
};
|
|
||||||
res = parseArray(context.parser, res, "display");
|
|
||||||
// Count number of columns = maximum number of cells in each row.
|
|
||||||
// At the same time, prepend empty group {} at beginning of every second
|
|
||||||
// cell in each row (starting with second cell) so that operators become
|
|
||||||
// binary. This behavior is implemented in amsmath's \start@aligned.
|
|
||||||
const emptyGroup = new ParseNode("ordgroup", [], context.mode);
|
|
||||||
let numCols = 0;
|
|
||||||
res.value.body.forEach(function(row) {
|
|
||||||
for (let i = 1; i < row.length; i += 2) {
|
|
||||||
// Modify ordgroup node within styling node
|
|
||||||
const ordgroup = row[i].value.value[0];
|
|
||||||
ordgroup.value.unshift(emptyGroup);
|
|
||||||
}
|
|
||||||
if (numCols < row.length) {
|
|
||||||
numCols = row.length;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (let i = 0; i < numCols; ++i) {
|
|
||||||
let align = "r";
|
|
||||||
let pregap = 0;
|
|
||||||
if (i % 2 === 1) {
|
|
||||||
align = "l";
|
|
||||||
} else if (i > 0) {
|
|
||||||
pregap = 1; // one \quad between columns
|
|
||||||
}
|
|
||||||
res.value.cols[i] = {
|
|
||||||
type: "align",
|
|
||||||
align: align,
|
|
||||||
pregap: pregap,
|
|
||||||
postgap: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
htmlBuilder,
|
htmlBuilder,
|
||||||
mathmlBuilder,
|
mathmlBuilder,
|
||||||
});
|
});
|
||||||
@@ -484,3 +515,20 @@ defineEnvironment({
|
|||||||
htmlBuilder,
|
htmlBuilder,
|
||||||
mathmlBuilder,
|
mathmlBuilder,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// alignat environment is like an align environment, but one must explicitly
|
||||||
|
// specify maximum number of columns in each row, and can adjust spacing between
|
||||||
|
// each columns.
|
||||||
|
defineEnvironment({
|
||||||
|
type: "array",
|
||||||
|
names: ["alignedat"],
|
||||||
|
// One for numbered and for unnumbered;
|
||||||
|
// but, KaTeX doesn't supports math numbering yet,
|
||||||
|
// they make no difference for now.
|
||||||
|
props: {
|
||||||
|
numArgs: 1,
|
||||||
|
},
|
||||||
|
handler: alignedHandler,
|
||||||
|
htmlBuilder,
|
||||||
|
mathmlBuilder,
|
||||||
|
});
|
||||||
|
BIN
test/screenshotter/images/Alignedat-chrome.png
Normal file
BIN
test/screenshotter/images/Alignedat-chrome.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
test/screenshotter/images/Alignedat-firefox.png
Normal file
BIN
test/screenshotter/images/Alignedat-firefox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@@ -22,6 +22,11 @@ Aligned: |
|
|||||||
a &= 1 & b &= 2 \\
|
a &= 1 & b &= 2 \\
|
||||||
3a &= 3 & 17b &= 34
|
3a &= 3 & 17b &= 34
|
||||||
\end{aligned}
|
\end{aligned}
|
||||||
|
Alignedat: |
|
||||||
|
\begin{alignedat}{3}
|
||||||
|
a &= 1 & b &= 2 &\quad c &= 3\\
|
||||||
|
3a &= 3 & 17b &= 34 &\quad 400c &= 1200
|
||||||
|
\end{alignedat}
|
||||||
Arrays: |
|
Arrays: |
|
||||||
\left(\begin{array}{|rl|c||}
|
\left(\begin{array}{|rl|c||}
|
||||||
1&2&3\\
|
1&2&3\\
|
||||||
|
Reference in New Issue
Block a user