UNPKG

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