Calculate math classes from outputs, not inputs.
It's important to get spacing right that the domTree classes reflect math atom types. So use those types exclusively, rather than repeating the type mapping twice (once when building spans, once in getTypeOfGroup). * Remove getTypeOfGroup. * Add getTypeOfDomTree (simpler). * Adjust supsub type calculation. * Adjust delimsizing internals.
This commit is contained in:
parent
dc79b91dbf
commit
982e7be597
|
@ -105,66 +105,20 @@ var buildExpression = function(expression, options, isRealGroup) {
|
|||
return groups;
|
||||
};
|
||||
|
||||
// List of types used by getTypeOfGroup,
|
||||
// see https://github.com/Khan/KaTeX/wiki/Examining-TeX#group-types
|
||||
var groupToType = {
|
||||
mathord: "mord",
|
||||
textord: "mord",
|
||||
bin: "mbin",
|
||||
rel: "mrel",
|
||||
text: "mord",
|
||||
open: "mopen",
|
||||
close: "mclose",
|
||||
inner: "minner",
|
||||
genfrac: "mord",
|
||||
array: "mord",
|
||||
spacing: "mord",
|
||||
punct: "mpunct",
|
||||
ordgroup: "mord",
|
||||
op: "mop",
|
||||
katex: "mord",
|
||||
overline: "mord",
|
||||
underline: "mord",
|
||||
rule: "mord",
|
||||
leftright: "minner",
|
||||
sqrt: "mord",
|
||||
accent: "mord",
|
||||
llap: "mord",
|
||||
rlap: "mord",
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the final math type of an expression, given its group type. This type is
|
||||
* used to determine spacing between elements, and affects bin elements by
|
||||
* causing them to change depending on what types are around them. This type
|
||||
* must be attached to the outermost node of an element as a CSS class so that
|
||||
* spacing with its surrounding elements works correctly.
|
||||
*
|
||||
* Some elements can be mapped one-to-one from group type to math type, and
|
||||
* those are listed in the `groupToType` table.
|
||||
*
|
||||
* Others (usually elements that wrap around other elements) often have
|
||||
* recursive definitions, and thus call `getTypeOfGroup` on their inner
|
||||
* elements.
|
||||
*/
|
||||
var getTypeOfGroup = function(group) {
|
||||
if (group == null) {
|
||||
// Like when typesetting $^3$
|
||||
return groupToType.mathord;
|
||||
} else if (group.type === "supsub") {
|
||||
return getTypeOfGroup(group.value.base);
|
||||
} else if (group.type === "color" || group.type === "sizing"
|
||||
|| group.type === "styling") {
|
||||
// Return type of rightmost element of group.
|
||||
var atoms = group.value.value;
|
||||
return getTypeOfGroup(atoms[atoms.length - 1]);
|
||||
} else if (group.type === "font") {
|
||||
return getTypeOfGroup(group.value.body);
|
||||
} else if (group.type === "delimsizing") {
|
||||
return groupToType[group.value.delimType];
|
||||
// Return math atom class (mclass) of a domTree.
|
||||
var getTypeOfDomTree = function(node) {
|
||||
if (node instanceof domTree.documentFragment) {
|
||||
if (node.children.length) {
|
||||
return getTypeOfDomTree(
|
||||
node.children[node.children.length - 1]);
|
||||
}
|
||||
} else {
|
||||
return groupToType[group.type];
|
||||
if (utils.contains(["mord", "mop", "mbin", "mrel", "mopen", "mclose",
|
||||
"mpunct", "minner"], node.classes[0])) {
|
||||
return node.classes[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -437,7 +391,8 @@ groupTypes.supsub = function(group, options) {
|
|||
}
|
||||
|
||||
// We ensure to wrap the supsub vlist in a span.msupsub to reset text-align
|
||||
return makeSpan([getTypeOfGroup(group.value.base)],
|
||||
var mclass = getTypeOfDomTree(base) || "mord";
|
||||
return makeSpan([mclass],
|
||||
[base, makeSpan(["msupsub"], [supsub])],
|
||||
options);
|
||||
};
|
||||
|
@ -1200,13 +1155,13 @@ groupTypes.delimsizing = function(group, options) {
|
|||
if (delim === ".") {
|
||||
// Empty delimiters still count as elements, even though they don't
|
||||
// show anything.
|
||||
return makeSpan([groupToType[group.value.delimType]]);
|
||||
return makeSpan([group.value.mclass]);
|
||||
}
|
||||
|
||||
// Use delimiter.sizedDelim to generate the delimiter.
|
||||
return delimiter.sizedDelim(
|
||||
delim, group.value.size, options, group.mode,
|
||||
[groupToType[group.value.delimType]]);
|
||||
[group.value.mclass]);
|
||||
};
|
||||
|
||||
groupTypes.leftright = function(group, options) {
|
||||
|
|
|
@ -358,10 +358,10 @@ groupTypes.delimsizing = function(group) {
|
|||
|
||||
var node = new mathMLTree.MathNode("mo", children);
|
||||
|
||||
if (group.value.delimType === "open" ||
|
||||
group.value.delimType === "close") {
|
||||
if (group.value.mclass === "mopen" ||
|
||||
group.value.mclass === "mclose") {
|
||||
// Only some of the delimsizing functions act as fences, and they
|
||||
// return "open" or "close" delimTypes.
|
||||
// return "mopen" or "mclose" mclass.
|
||||
node.setAttribute("fence", "true");
|
||||
} else {
|
||||
// Explicitly disable fencing if it's not a fence, to override the
|
||||
|
|
|
@ -238,22 +238,22 @@ defineFunction("\\phantom", {
|
|||
|
||||
// Extra data needed for the delimiter handler down below
|
||||
var delimiterSizes = {
|
||||
"\\bigl" : {type: "open", size: 1},
|
||||
"\\Bigl" : {type: "open", size: 2},
|
||||
"\\biggl": {type: "open", size: 3},
|
||||
"\\Biggl": {type: "open", size: 4},
|
||||
"\\bigr" : {type: "close", size: 1},
|
||||
"\\Bigr" : {type: "close", size: 2},
|
||||
"\\biggr": {type: "close", size: 3},
|
||||
"\\Biggr": {type: "close", size: 4},
|
||||
"\\bigm" : {type: "rel", size: 1},
|
||||
"\\Bigm" : {type: "rel", size: 2},
|
||||
"\\biggm": {type: "rel", size: 3},
|
||||
"\\Biggm": {type: "rel", size: 4},
|
||||
"\\big" : {type: "textord", size: 1},
|
||||
"\\Big" : {type: "textord", size: 2},
|
||||
"\\bigg" : {type: "textord", size: 3},
|
||||
"\\Bigg" : {type: "textord", size: 4},
|
||||
"\\bigl" : {mclass: "mopen", size: 1},
|
||||
"\\Bigl" : {mclass: "mopen", size: 2},
|
||||
"\\biggl": {mclass: "mopen", size: 3},
|
||||
"\\Biggl": {mclass: "mopen", size: 4},
|
||||
"\\bigr" : {mclass: "mclose", size: 1},
|
||||
"\\Bigr" : {mclass: "mclose", size: 2},
|
||||
"\\biggr": {mclass: "mclose", size: 3},
|
||||
"\\Biggr": {mclass: "mclose", size: 4},
|
||||
"\\bigm" : {mclass: "mrel", size: 1},
|
||||
"\\Bigm" : {mclass: "mrel", size: 2},
|
||||
"\\biggm": {mclass: "mrel", size: 3},
|
||||
"\\Biggm": {mclass: "mrel", size: 4},
|
||||
"\\big" : {mclass: "mord", size: 1},
|
||||
"\\Big" : {mclass: "mord", size: 2},
|
||||
"\\bigg" : {mclass: "mord", size: 3},
|
||||
"\\Bigg" : {mclass: "mord", size: 4},
|
||||
};
|
||||
|
||||
var delimiters = [
|
||||
|
@ -472,7 +472,7 @@ defineFunction([
|
|||
return {
|
||||
type: "delimsizing",
|
||||
size: delimiterSizes[context.funcName].size,
|
||||
delimType: delimiterSizes[context.funcName].type,
|
||||
mclass: delimiterSizes[context.funcName].mclass,
|
||||
value: delim.value,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -883,8 +883,8 @@ describe("A delimiter sizing parser", function() {
|
|||
var leftParse = getParsed(normalDelim)[0];
|
||||
var rightParse = getParsed(bigDelim)[0];
|
||||
|
||||
expect(leftParse.value.delimType).toEqual("open");
|
||||
expect(rightParse.value.delimType).toEqual("close");
|
||||
expect(leftParse.value.mclass).toEqual("mopen");
|
||||
expect(rightParse.value.mclass).toEqual("mclose");
|
||||
});
|
||||
|
||||
it("should parse the correct size delimiter", function() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user