mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 03:08:40 +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,
|
limits: boolean,
|
||||||
symbol: boolean,
|
symbol: boolean,
|
||||||
alwaysHandleSupSub?: boolean,
|
alwaysHandleSupSub?: boolean,
|
||||||
|
suppressBaseShift?: boolean,
|
||||||
body?: string,
|
body?: string,
|
||||||
value?: ParseNode<*>[],
|
value?: ParseNode<*>[],
|
||||||
|},
|
|},
|
||||||
|
@@ -70,26 +70,48 @@ defineFunction("mclass", [
|
|||||||
defineFunction("mclass", ["\\stackrel", "\\overset", "\\underset"], {
|
defineFunction("mclass", ["\\stackrel", "\\overset", "\\underset"], {
|
||||||
numArgs: 2,
|
numArgs: 2,
|
||||||
}, function(context, args) {
|
}, function(context, args) {
|
||||||
const mathAxisArg = args[1];
|
const baseArg = args[1];
|
||||||
const shiftedArg = args[0];
|
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",
|
type: "op",
|
||||||
limits: true,
|
limits: true,
|
||||||
alwaysHandleSupSub: true,
|
alwaysHandleSupSub: true,
|
||||||
symbol: false,
|
symbol: false,
|
||||||
value: ordargument(mathAxisArg),
|
suppressBaseShift: context.funcName !== "\\stackrel",
|
||||||
}, mathAxisArg.mode);
|
value: ordargument(baseArg),
|
||||||
|
}, baseArg.mode);
|
||||||
|
|
||||||
const supsub = new ParseNode("supsub", {
|
const supsub = new ParseNode("supsub", {
|
||||||
base: xAxisOp,
|
base: baseOp,
|
||||||
sup: context.funcName === "\\underset" ? null : shiftedArg,
|
sup: context.funcName === "\\underset" ? null : shiftedArg,
|
||||||
sub: context.funcName === "\\underset" ? shiftedArg : null,
|
sub: context.funcName === "\\underset" ? shiftedArg : null,
|
||||||
}, shiftedArg.mode);
|
}, shiftedArg.mode);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "mclass",
|
type: "mclass",
|
||||||
mclass: "mrel",
|
mclass: mclass,
|
||||||
value: [supsub],
|
value: [supsub],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@@ -72,8 +72,9 @@ const htmlBuilder = (group, options) => {
|
|||||||
// If content of op is a single symbol, shift it vertically.
|
// If content of op is a single symbol, shift it vertically.
|
||||||
let baseShift = 0;
|
let baseShift = 0;
|
||||||
let slant = 0;
|
let slant = 0;
|
||||||
if (base instanceof domTree.symbolNode) {
|
if (base instanceof domTree.symbolNode && !group.value.suppressBaseShift) {
|
||||||
// Shift the symbol so its center lies on the axis (rule 13). It
|
// 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
|
// appears that our fonts have the centers of the symbols already
|
||||||
// almost on the axis, so these numbers are very small. Note we
|
// 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
|
// 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}}}
|
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: |
|
OverUnderset: |
|
||||||
\begin{array}{l}
|
\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}}\\
|
{\displaystyle\lim_{t\underset{>0}\to0}}\\
|
||||||
a+b+c+d\overset{b+c=0}\longrightarrow a+d\\
|
a+b+c+d\overset{b+c=0}\longrightarrow a+d\\
|
||||||
\overset { x = y } { \sqrt { a b } }
|
\overset { x = y } { \sqrt { a b } }
|
||||||
|
Reference in New Issue
Block a user