Spaces:
Sleeping
Sleeping
File size: 3,610 Bytes
9d1374f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | // smash, with optional [tb], as in AMS
import defineFunction from "../defineFunction";
import {makeSpan, makeVList} from "../buildCommon";
import {MathNode} from "../mathMLTree";
import {assertNodeType, assertSymbolNodeType} from "../parseNode";
import * as html from "../buildHTML";
import * as mml from "../buildMathML";
defineFunction({
type: "smash",
names: ["\\smash"],
props: {
numArgs: 1,
numOptionalArgs: 1,
allowedInText: true,
},
handler: ({parser}, args, optArgs) => {
let smashHeight = false;
let smashDepth = false;
const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup");
if (tbArg) {
// Optional [tb] argument is engaged.
// ref: amsmath: \renewcommand{\smash}[1][tb]{%
// def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
let letter = "";
for (let i = 0; i < tbArg.body.length; ++i) {
const node = tbArg.body[i];
letter = assertSymbolNodeType(node).text;
if (letter === "t") {
smashHeight = true;
} else if (letter === "b") {
smashDepth = true;
} else {
smashHeight = false;
smashDepth = false;
break;
}
}
} else {
smashHeight = true;
smashDepth = true;
}
const body = args[0];
return {
type: "smash",
mode: parser.mode,
body,
smashHeight,
smashDepth,
};
},
htmlBuilder: (group, options) => {
const node = makeSpan(
[], [html.buildGroup(group.body, options)]);
if (!group.smashHeight && !group.smashDepth) {
return node;
}
if (group.smashHeight) {
node.height = 0;
}
if (group.smashDepth) {
node.depth = 0;
}
if (group.smashHeight && group.smashDepth) {
// Symmetric \smash can stay in inline layout.
return makeSpan(["mord", "smash"], [node], options);
}
// In order to influence makeVList for asymmetric smashing, we have to
// reset the children.
if (node.children) {
for (let i = 0; i < node.children.length; i++) {
if (group.smashHeight) {
node.children[i].height = 0;
}
if (group.smashDepth) {
node.children[i].depth = 0;
}
}
}
// At this point, we've reset the TeX-like height and depth values.
// But the span still has an HTML line height.
// makeVList applies "display: table-cell", which prevents the browser
// from acting on that line height. So we'll call makeVList now.
const smashedNode = makeVList({
positionType: "firstBaseline",
children: [{type: "elem", elem: node}],
}, options);
// For spacing, TeX treats \smash as a math group (same spacing as ord).
return makeSpan(["mord"], [smashedNode], options);
},
mathmlBuilder: (group, options) => {
const node = new MathNode(
"mpadded", [mml.buildGroup(group.body, options)]);
if (group.smashHeight) {
node.setAttribute("height", "0px");
}
if (group.smashDepth) {
node.setAttribute("depth", "0px");
}
return node;
},
});
|