mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-04 18:58:39 +00:00
Adjust \underset alignment and spacing (#1290)
* Support Unicode \ll and \lll Fixes issue #1271 * Adjust \underset alignment and spacing Fixes issue #1288. 1. Fixes vertical alignment by keeping the base element on the baseline. 2. Assigns horizontal spacing to \underset in a manner that aligns with LaTeX `\binrel` * Fix flow error * Add comment * Allow for shift of mathops * Update screenshots * Test for nested ordgroups * Set \stackrel spacing class to mrel * Fix lint error * Better determination of atom type * Add comment. * Add `suppressBaseShift` to ParseNodeTypes
This commit is contained in:
@@ -68,6 +68,7 @@ type ParseNodeTypes = {
|
||||
limits: boolean,
|
||||
symbol: boolean,
|
||||
alwaysHandleSupSub?: boolean,
|
||||
suppressBaseShift?: boolean,
|
||||
body?: string,
|
||||
value?: ParseNode<*>[],
|
||||
|},
|
||||
|
@@ -70,26 +70,48 @@ defineFunction("mclass", [
|
||||
defineFunction("mclass", ["\\stackrel", "\\overset", "\\underset"], {
|
||||
numArgs: 2,
|
||||
}, function(context, args) {
|
||||
const mathAxisArg = args[1];
|
||||
const baseArg = args[1];
|
||||
const shiftedArg = args[0];
|
||||
|
||||
const xAxisOp = new ParseNode("op", {
|
||||
let mclass = "mrel"; // default. May change below.
|
||||
if (context.funcName !== "\\stackrel") {
|
||||
// LaTeX applies \binrel spacing to \overset and \underset.
|
||||
// \binrel spacing varies with (bin|rel|ord) of the atom in the argument.
|
||||
// We'll do the same.
|
||||
let atomType = "";
|
||||
if (baseArg.type === "ordgroup") {
|
||||
atomType = baseArg.value[0].type;
|
||||
} else {
|
||||
atomType = baseArg.type;
|
||||
}
|
||||
if (/^(bin|rel)$/.test(atomType)) {
|
||||
mclass = "m" + atomType;
|
||||
} else {
|
||||
// This may capture some instances in which the baseArg is more than
|
||||
// just a single symbol. Say a \overset inside an \overset.
|
||||
// TODO: A more comprehensive way to determine the baseArg type.
|
||||
mclass = "mord";
|
||||
}
|
||||
}
|
||||
|
||||
const baseOp = new ParseNode("op", {
|
||||
type: "op",
|
||||
limits: true,
|
||||
alwaysHandleSupSub: true,
|
||||
symbol: false,
|
||||
value: ordargument(mathAxisArg),
|
||||
}, mathAxisArg.mode);
|
||||
suppressBaseShift: context.funcName !== "\\stackrel",
|
||||
value: ordargument(baseArg),
|
||||
}, baseArg.mode);
|
||||
|
||||
const supsub = new ParseNode("supsub", {
|
||||
base: xAxisOp,
|
||||
base: baseOp,
|
||||
sup: context.funcName === "\\underset" ? null : shiftedArg,
|
||||
sub: context.funcName === "\\underset" ? shiftedArg : null,
|
||||
}, shiftedArg.mode);
|
||||
|
||||
return {
|
||||
type: "mclass",
|
||||
mclass: "mrel",
|
||||
mclass: mclass,
|
||||
value: [supsub],
|
||||
};
|
||||
});
|
||||
|
@@ -72,8 +72,9 @@ const htmlBuilder = (group, options) => {
|
||||
// If content of op is a single symbol, shift it vertically.
|
||||
let baseShift = 0;
|
||||
let slant = 0;
|
||||
if (base instanceof domTree.symbolNode) {
|
||||
// Shift the symbol so its center lies on the axis (rule 13). It
|
||||
if (base instanceof domTree.symbolNode && !group.value.suppressBaseShift) {
|
||||
// We suppress the shift of the base of \overset and \underset. Otherwise,
|
||||
// shift the symbol so its center lies on the axis (rule 13). It
|
||||
// appears that our fonts have the centers of the symbols already
|
||||
// almost on the axis, so these numbers are very small. Note we
|
||||
// don't actually apply this here, but instead it is used either in
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 18 KiB |
@@ -218,7 +218,7 @@ OpLimits: |
|
||||
OverUnderline: x\underline{x}\underline{\underline{x}}\underline{x_{x_{x_x}}}\underline{x^{x^{x^x}}}\overline{x}\overline{x}\overline{x^{x^{x^x}}} \blue{\overline{\underline{x}}\underline{\overline{x}}}
|
||||
OverUnderset: |
|
||||
\begin{array}{l}
|
||||
x\overset?=1 \quad \underset{*}{x}^2 \\
|
||||
x\overset?=1 \quad \underset{*}{x}^2 \quad \overset{a}{b}b\underset{a}{b}b \\
|
||||
{\displaystyle\lim_{t\underset{>0}\to0}}\\
|
||||
a+b+c+d\overset{b+c=0}\longrightarrow a+d\\
|
||||
\overset { x = y } { \sqrt { a b } }
|
||||
|
Reference in New Issue
Block a user