|
|
|
import defineFunction, {ordargument} from "../defineFunction"; |
|
import defineMacro from "../defineMacro"; |
|
import buildCommon from "../buildCommon"; |
|
import mathMLTree from "../mathMLTree"; |
|
import {SymbolNode} from "../domTree"; |
|
import {assembleSupSub} from "./utils/assembleSupSub"; |
|
import {assertNodeType} from "../parseNode"; |
|
|
|
import * as html from "../buildHTML"; |
|
import * as mml from "../buildMathML"; |
|
|
|
import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction"; |
|
import type {ParseNode} from "../parseNode"; |
|
|
|
|
|
|
|
|
|
export const htmlBuilder: HtmlBuilderSupSub<"operatorname"> = (grp, options) => { |
|
|
|
let supGroup; |
|
let subGroup; |
|
let hasLimits = false; |
|
let group: ParseNode<"operatorname">; |
|
if (grp.type === "supsub") { |
|
|
|
|
|
|
|
supGroup = grp.sup; |
|
subGroup = grp.sub; |
|
group = assertNodeType(grp.base, "operatorname"); |
|
hasLimits = true; |
|
} else { |
|
group = assertNodeType(grp, "operatorname"); |
|
} |
|
|
|
let base; |
|
if (group.body.length > 0) { |
|
const body = group.body.map(child => { |
|
|
|
const childText = child.text; |
|
if (typeof childText === "string") { |
|
return { |
|
type: "textord", |
|
mode: child.mode, |
|
text: childText, |
|
}; |
|
} else { |
|
return child; |
|
} |
|
}); |
|
|
|
|
|
const expression = html.buildExpression( |
|
body, options.withFont("mathrm"), true); |
|
|
|
for (let i = 0; i < expression.length; i++) { |
|
const child = expression[i]; |
|
if (child instanceof SymbolNode) { |
|
|
|
|
|
child.text = child.text.replace(/\u2212/, "-") |
|
.replace(/\u2217/, "*"); |
|
} |
|
} |
|
base = buildCommon.makeSpan(["mop"], expression, options); |
|
} else { |
|
base = buildCommon.makeSpan(["mop"], [], options); |
|
} |
|
|
|
if (hasLimits) { |
|
return assembleSupSub(base, supGroup, subGroup, options, |
|
options.style, 0, 0); |
|
|
|
} else { |
|
return base; |
|
} |
|
}; |
|
|
|
const mathmlBuilder: MathMLBuilder<"operatorname"> = (group, options) => { |
|
|
|
let expression = mml.buildExpression( |
|
group.body, options.withFont("mathrm")); |
|
|
|
|
|
let isAllString = true; |
|
for (let i = 0; i < expression.length; i++) { |
|
const node = expression[i]; |
|
if (node instanceof mathMLTree.SpaceNode) { |
|
|
|
} else if (node instanceof mathMLTree.MathNode) { |
|
switch (node.type) { |
|
case "mi": |
|
case "mn": |
|
case "ms": |
|
case "mspace": |
|
case "mtext": |
|
break; |
|
case "mo": { |
|
const child = node.children[0]; |
|
if (node.children.length === 1 && |
|
child instanceof mathMLTree.TextNode) { |
|
child.text = |
|
child.text.replace(/\u2212/, "-") |
|
.replace(/\u2217/, "*"); |
|
} else { |
|
isAllString = false; |
|
} |
|
break; |
|
} |
|
default: |
|
isAllString = false; |
|
} |
|
} else { |
|
isAllString = false; |
|
} |
|
} |
|
|
|
if (isAllString) { |
|
|
|
const word = expression.map(node => node.toText()).join(""); |
|
expression = [new mathMLTree.TextNode(word)]; |
|
} |
|
|
|
const identifier = new mathMLTree.MathNode("mi", expression); |
|
identifier.setAttribute("mathvariant", "normal"); |
|
|
|
|
|
|
|
const operator = new mathMLTree.MathNode("mo", |
|
[mml.makeText("\u2061", "text")]); |
|
|
|
if (group.parentIsSupSub) { |
|
return new mathMLTree.MathNode("mrow", [identifier, operator]); |
|
} else { |
|
return mathMLTree.newDocumentFragment([identifier, operator]); |
|
} |
|
}; |
|
|
|
|
|
|
|
defineFunction({ |
|
type: "operatorname", |
|
names: ["\\operatorname@", "\\operatornamewithlimits"], |
|
props: { |
|
numArgs: 1, |
|
}, |
|
handler: ({parser, funcName}, args) => { |
|
const body = args[0]; |
|
return { |
|
type: "operatorname", |
|
mode: parser.mode, |
|
body: ordargument(body), |
|
alwaysHandleSupSub: (funcName === "\\operatornamewithlimits"), |
|
limits: false, |
|
parentIsSupSub: false, |
|
}; |
|
}, |
|
htmlBuilder, |
|
mathmlBuilder, |
|
}); |
|
|
|
defineMacro("\\operatorname", |
|
"\\@ifstar\\operatornamewithlimits\\operatorname@"); |
|
|