mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-09 13:08:40 +00:00
\@binrel command and refactor (#1487)
* \@binrel command and refactor New `\@binrel{x}{y}` command renders `y` as if it's a bin/rel/ord like `x`. This is equivalent to AMSTeX's `\binrel@{x}\binrel@@{y}`. It will hopefully be useful for macros, such as `\pmb` (#1418). Also refactor the (already duplicated) code for implementing this functionality into buildCommon.binrelClass. * Add tests; fix flow error * Another test * Move binrelClass to functions/mclass.js * Remove expensive array destructuring polyfill
This commit is contained in:
committed by
Kevin Barabash
parent
8f5239c272
commit
578877764d
@@ -3,6 +3,7 @@ import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode from "../ParseNode";
|
||||
import type {AnyParseNode} from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -41,6 +42,37 @@ defineFunction({
|
||||
mathmlBuilder,
|
||||
});
|
||||
|
||||
export const binrelClass = (arg: AnyParseNode) => {
|
||||
// \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
|
||||
// (by rendering separately and with {}s before and after, and measuring
|
||||
// the change in spacing). We'll do roughly the same by detecting the
|
||||
// atom type directly.
|
||||
const atomType = (arg.type === "ordgroup" &&
|
||||
arg.value.length ? arg.value[0].type : arg.type);
|
||||
if (/^(bin|rel)$/.test(atomType)) {
|
||||
return "m" + atomType;
|
||||
} else {
|
||||
return "mord";
|
||||
}
|
||||
};
|
||||
|
||||
// \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
|
||||
// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
|
||||
defineFunction({
|
||||
type: "mclass",
|
||||
names: ["\\@binrel"],
|
||||
props: {
|
||||
numArgs: 2,
|
||||
},
|
||||
handler({parser}, args) {
|
||||
return new ParseNode("mclass", {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(args[0]),
|
||||
value: [args[1]],
|
||||
}, parser.mode);
|
||||
},
|
||||
});
|
||||
|
||||
// Build a relation or stacked op by placing one symbol on top of another
|
||||
defineFunction({
|
||||
type: "mclass",
|
||||
@@ -52,21 +84,12 @@ defineFunction({
|
||||
const baseArg = args[1];
|
||||
const shiftedArg = args[0];
|
||||
|
||||
let mclass = "mrel"; // default. May change below.
|
||||
let mclass;
|
||||
if (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.
|
||||
const atomType = (baseArg.type === "ordgroup" &&
|
||||
baseArg.value.length ? baseArg.value[0].type : 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";
|
||||
}
|
||||
// LaTeX applies \binrel spacing to \overset and \underset.
|
||||
mclass = binrelClass(baseArg);
|
||||
} else {
|
||||
mclass = "mrel"; // for \stackrel
|
||||
}
|
||||
|
||||
const baseOp = new ParseNode("op", {
|
||||
|
Reference in New Issue
Block a user