import buildCommon from "../../buildCommon";
import * as html from "../../buildHTML";
import utils from "../../utils";
import type {StyleInterface} from "../../Style";
import type Options from "../../Options";
import type {DomSpan, SymbolNode} from "../../domTree";
import type {AnyParseNode} from "../../parseNode";
import {makeEm} from "../../units";
export const assembleSupSub = (
base: DomSpan | SymbolNode,
supGroup: ?AnyParseNode,
subGroup: ?AnyParseNode,
options: Options,
style: StyleInterface,
slant: number,
baseShift: number,
): DomSpan => {
base = buildCommon.makeSpan([], [base]);
const subIsSingleCharacter = subGroup && utils.isCharacterBox(subGroup);
let sub;
let sup;
if (supGroup) {
const elem = html.buildGroup(
supGroup, options.havingStyle(style.sup()), options);
sup = {
elem,
kern: Math.max(
options.fontMetrics().bigOpSpacing1,
options.fontMetrics().bigOpSpacing3 - elem.depth),
};
}
if (subGroup) {
const elem = html.buildGroup(
subGroup, options.havingStyle(style.sub()), options);
sub = {
elem,
kern: Math.max(
options.fontMetrics().bigOpSpacing2,
options.fontMetrics().bigOpSpacing4 - elem.height),
};
}
let finalGroup;
if (sup && sub) {
const bottom = options.fontMetrics().bigOpSpacing5 +
sub.elem.height + sub.elem.depth +
sub.kern +
base.depth + baseShift;
finalGroup = buildCommon.makeVList({
positionType: "bottom",
positionData: bottom,
children: [
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
{type: "elem", elem: sub.elem, marginLeft: makeEm(-slant)},
{type: "kern", size: sub.kern},
{type: "elem", elem: base},
{type: "kern", size: sup.kern},
{type: "elem", elem: sup.elem, marginLeft: makeEm(slant)},
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
],
}, options);
} else if (sub) {
const top = base.height - baseShift;
finalGroup = buildCommon.makeVList({
positionType: "top",
positionData: top,
children: [
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
{type: "elem", elem: sub.elem, marginLeft: makeEm(-slant)},
{type: "kern", size: sub.kern},
{type: "elem", elem: base},
],
}, options);
} else if (sup) {
const bottom = base.depth + baseShift;
finalGroup = buildCommon.makeVList({
positionType: "bottom",
positionData: bottom,
children: [
{type: "elem", elem: base},
{type: "kern", size: sup.kern},
{type: "elem", elem: sup.elem, marginLeft: makeEm(slant)},
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
],
}, options);
} else {
return base;
}
const parts = [finalGroup];
if (sub && slant !== 0 && !subIsSingleCharacter) {
const spacer = buildCommon.makeSpan(["mspace"], [], options);
spacer.style.marginRight = makeEm(slant);
parts.unshift(spacer);
}
return buildCommon.makeSpan(["mop", "op-limits"], parts, options);
};