stuff
This commit is contained in:
parent
bc92231240
commit
b8225c639e
11904 changed files with 1472749 additions and 133 deletions
161
node_modules/katex/src/functions/operatorname.ts
generated
vendored
Normal file
161
node_modules/katex/src/functions/operatorname.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import defineMacro from "../defineMacro";
|
||||
import {makeSpan} from "../buildCommon";
|
||||
import {MathNode, newDocumentFragment, SpaceNode, TextNode} 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 {AnyParseNode, ParseNode} from "../parseNode";
|
||||
|
||||
// NOTE: Unlike most `htmlBuilder`s, this one handles not only
|
||||
// "operatorname", but also "supsub" since \operatorname* can
|
||||
// affect super/subscripting.
|
||||
export const htmlBuilder: HtmlBuilderSupSub<"operatorname"> = (grp, options) => {
|
||||
// Operators are handled in the TeXbook pg. 443-444, rule 13(a).
|
||||
let supGroup;
|
||||
let subGroup;
|
||||
let hasLimits = false;
|
||||
let group: ParseNode<"operatorname">;
|
||||
if (grp.type === "supsub") {
|
||||
// If we have limits, supsub will pass us its group to handle. Pull
|
||||
// out the superscript and subscript and set the group to the op in
|
||||
// its base.
|
||||
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): AnyParseNode => {
|
||||
const childText = "text" in child ? child.text : undefined;
|
||||
if (typeof childText === "string") {
|
||||
return {
|
||||
type: "textord",
|
||||
mode: child.mode,
|
||||
text: childText,
|
||||
};
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
});
|
||||
|
||||
// Consolidate function names into symbol characters.
|
||||
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) {
|
||||
// Per amsopn package,
|
||||
// change minus to hyphen and \ast to asterisk
|
||||
child.text = child.text.replace(/\u2212/, "-")
|
||||
.replace(/\u2217/, "*");
|
||||
}
|
||||
}
|
||||
base = makeSpan(["mop"], expression, options);
|
||||
} else {
|
||||
base = makeSpan(["mop"], [], options);
|
||||
}
|
||||
|
||||
if (hasLimits) {
|
||||
return assembleSupSub(base, supGroup, subGroup, options,
|
||||
options.style, 0, 0);
|
||||
|
||||
} else {
|
||||
return base;
|
||||
}
|
||||
};
|
||||
|
||||
const mathmlBuilder: MathMLBuilder<"operatorname"> = (group, options) => {
|
||||
// The steps taken here are similar to the html version.
|
||||
let expression: Array<MathNode | TextNode> = mml.buildExpression(
|
||||
group.body, options.withFont("mathrm"));
|
||||
|
||||
// Is expression a string or has it something like a fraction?
|
||||
let isAllString = true; // default
|
||||
for (let i = 0; i < expression.length; i++) {
|
||||
const node = expression[i];
|
||||
if (node instanceof SpaceNode) {
|
||||
// Do nothing
|
||||
} else if (node instanceof MathNode) {
|
||||
switch (node.type) {
|
||||
case "mi":
|
||||
case "mn":
|
||||
case "mspace":
|
||||
case "mtext":
|
||||
break; // Do nothing yet.
|
||||
case "mo": {
|
||||
const child = node.children[0];
|
||||
if (node.children.length === 1 &&
|
||||
child instanceof TextNode) {
|
||||
child.text =
|
||||
child.text.replace(/\u2212/, "-")
|
||||
.replace(/\u2217/, "*");
|
||||
} else {
|
||||
isAllString = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
isAllString = false;
|
||||
}
|
||||
} else {
|
||||
isAllString = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAllString) {
|
||||
// Write a single TextNode instead of multiple nested tags.
|
||||
const word = expression.map(node => node.toText()).join("");
|
||||
expression = [new TextNode(word)];
|
||||
}
|
||||
|
||||
const identifier = new MathNode("mi", expression);
|
||||
identifier.setAttribute("mathvariant", "normal");
|
||||
|
||||
// \u2061 is the same as ⁡
|
||||
// ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
|
||||
const operator = new MathNode("mo",
|
||||
[mml.makeText("\u2061", "text")]);
|
||||
|
||||
if (group.parentIsSupSub) {
|
||||
return new MathNode("mrow", [identifier, operator]);
|
||||
} else {
|
||||
return newDocumentFragment([identifier, operator]);
|
||||
}
|
||||
};
|
||||
|
||||
// \operatorname
|
||||
// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
|
||||
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@");
|
||||
Loading…
Add table
Add a link
Reference in a new issue