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:
Ron Kok
2018-05-09 21:13:37 -07:00
committed by ylemkimon
parent 5a4aedd882
commit 7b7b532fb6
6 changed files with 33 additions and 9 deletions

View File

@@ -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<*>[],
|}, |},

View File

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

View File

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

View File

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