mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-06 03:38:39 +00:00
Move HTML and MathML builders for symbol groups into src/functions/{symbolsOp,symbolsOrd}.js. (#1334)
* Move HTML and MathML builders for symbol groups into src/functions/{symbolsOp,symbolsOrd}.js.
This commit is contained in:
@@ -222,10 +222,10 @@ const boldsymbol = function(
|
||||
/**
|
||||
* Makes either a mathord or textord in the correct font and color.
|
||||
*/
|
||||
const makeOrd = function(
|
||||
group: ParseNode<*>,
|
||||
const makeOrd = function<NODETYPE: "textord" | "mathord">(
|
||||
group: ParseNode<NODETYPE>,
|
||||
options: Options,
|
||||
type: NodeType,
|
||||
type: NODETYPE,
|
||||
): domTree.symbolNode {
|
||||
const mode = group.mode;
|
||||
const value = group.value;
|
||||
|
@@ -242,28 +242,6 @@ export const makeNullDelimiter = function(options, classes) {
|
||||
* Simpler types come at the beginning, while complicated types come afterwards.
|
||||
*/
|
||||
export const groupTypes = {
|
||||
mathord: (group, options) => buildCommon.makeOrd(group, options, "mathord"),
|
||||
|
||||
textord: (group, options) => buildCommon.makeOrd(group, options, "textord"),
|
||||
|
||||
bin: (group, options) =>
|
||||
buildCommon.mathsym(group.value, group.mode, options, ["mbin"]),
|
||||
|
||||
rel: (group, options) =>
|
||||
buildCommon.mathsym(group.value, group.mode, options, ["mrel"]),
|
||||
|
||||
open: (group, options) =>
|
||||
buildCommon.mathsym(group.value, group.mode, options, ["mopen"]),
|
||||
|
||||
close: (group, options) =>
|
||||
buildCommon.mathsym(group.value, group.mode, options, ["mclose"]),
|
||||
|
||||
inner: (group, options) =>
|
||||
buildCommon.mathsym(group.value, group.mode, options, ["minner"]),
|
||||
|
||||
punct: (group, options) =>
|
||||
buildCommon.mathsym(group.value, group.mode, options, ["mpunct"]),
|
||||
|
||||
ordgroup: (group, options) => makeSpan(
|
||||
["mord"], buildExpression(group.value, options, true), options),
|
||||
|
||||
|
@@ -60,7 +60,7 @@ export const makeTextRow = function(body, options) {
|
||||
/**
|
||||
* Returns the math variant as a string or null if none is required.
|
||||
*/
|
||||
const getVariant = function(group, options) {
|
||||
export const getVariant = function(group, options) {
|
||||
const font = options.font;
|
||||
if (!font) {
|
||||
return null;
|
||||
@@ -96,97 +96,6 @@ const getVariant = function(group, options) {
|
||||
*/
|
||||
export const groupTypes = {};
|
||||
|
||||
const defaultVariant = {
|
||||
"mi": "italic",
|
||||
"mn": "normal",
|
||||
"mtext": "normal",
|
||||
};
|
||||
|
||||
groupTypes.mathord = function(group, options) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mi",
|
||||
[makeText(group.value, group.mode)]);
|
||||
|
||||
const variant = getVariant(group, options) || "italic";
|
||||
if (variant !== defaultVariant[node.type]) {
|
||||
node.setAttribute("mathvariant", variant);
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.textord = function(group, options) {
|
||||
const text = makeText(group.value, group.mode);
|
||||
|
||||
const variant = getVariant(group, options) || "normal";
|
||||
|
||||
let node;
|
||||
if (group.mode === 'text') {
|
||||
node = new mathMLTree.MathNode("mtext", [text]);
|
||||
} else if (/[0-9]/.test(group.value)) {
|
||||
// TODO(kevinb) merge adjacent <mn> nodes
|
||||
// do it as a post processing step
|
||||
node = new mathMLTree.MathNode("mn", [text]);
|
||||
} else if (group.value === "\\prime") {
|
||||
node = new mathMLTree.MathNode("mo", [text]);
|
||||
} else {
|
||||
node = new mathMLTree.MathNode("mi", [text]);
|
||||
}
|
||||
if (variant !== defaultVariant[node.type]) {
|
||||
node.setAttribute("mathvariant", variant);
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.bin = function(group, options) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [makeText(group.value, group.mode)]);
|
||||
|
||||
const variant = getVariant(group, options);
|
||||
if (variant === "bold-italic") {
|
||||
node.setAttribute("mathvariant", variant);
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.rel = function(group) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [makeText(group.value, group.mode)]);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.open = function(group) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [makeText(group.value, group.mode)]);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.close = function(group) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [makeText(group.value, group.mode)]);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.inner = function(group) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [makeText(group.value, group.mode)]);
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.punct = function(group) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [makeText(group.value, group.mode)]);
|
||||
|
||||
node.setAttribute("separator", "true");
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
groupTypes.ordgroup = function(group, options) {
|
||||
const inner = buildExpression(group.value, options);
|
||||
|
||||
|
@@ -26,6 +26,12 @@ export type FunctionHandler<NODETYPE: NodeType> = (
|
||||
optArgs: (?ParseNode<*>)[],
|
||||
) => NodeValue<NODETYPE>;
|
||||
|
||||
export type HtmlBuilder<NODETYPE> = (ParseNode<NODETYPE>, Options) => HtmlDomNode;
|
||||
export type MathMLBuilder<NODETYPE> = (
|
||||
group: ParseNode<NODETYPE>,
|
||||
options: Options,
|
||||
) => MathNode | TextNode | domTree.documentFragment;
|
||||
|
||||
export type FunctionPropSpec = {
|
||||
// The number of arguments the function takes.
|
||||
numArgs: number,
|
||||
@@ -106,16 +112,13 @@ type FunctionDefSpec<NODETYPE: NodeType> = {|
|
||||
|
||||
// This function returns an object representing the DOM structure to be
|
||||
// created when rendering the defined LaTeX function.
|
||||
htmlBuilder?: (group: ParseNode<NODETYPE>, options: Options) => HtmlDomNode,
|
||||
htmlBuilder?: HtmlBuilder<NODETYPE>,
|
||||
|
||||
// TODO: Currently functions/op.js returns documentFragment. Refactor it
|
||||
// and update the return type of this function.
|
||||
// This function returns an object representing the MathML structure to be
|
||||
// created when rendering the defined LaTeX function.
|
||||
mathmlBuilder?: (
|
||||
group: ParseNode<NODETYPE>,
|
||||
options: Options,
|
||||
) => MathNode | TextNode | domTree.documentFragment,
|
||||
mathmlBuilder?: MathMLBuilder<NODETYPE>,
|
||||
|};
|
||||
|
||||
/**
|
||||
@@ -198,6 +201,28 @@ export default function defineFunction<NODETYPE: NodeType>({
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this to register only the HTML and MathML builders for a function (e.g.
|
||||
* if the function's ParseNode is generated in Parser.js rather than via a
|
||||
* stand-alone handler provided to `defineFunction`).
|
||||
*/
|
||||
export function defineFunctionBuilders<NODETYPE: NodeType>({
|
||||
type, htmlBuilder, mathmlBuilder,
|
||||
}: {
|
||||
type: NODETYPE,
|
||||
htmlBuilder: HtmlBuilder<NODETYPE>,
|
||||
mathmlBuilder: MathMLBuilder<NODETYPE>,
|
||||
}) {
|
||||
defineFunction({
|
||||
type,
|
||||
names: [],
|
||||
props: {numArgs: 0},
|
||||
handler() { throw new Error('Should never be called.'); },
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
});
|
||||
}
|
||||
|
||||
// Since the corresponding buildHTML/buildMathML function expects a
|
||||
// list of elements, we normalize for different kinds of arguments
|
||||
export const ordargument = function(arg: ParseNode<*>): ParseNode<*>[] {
|
||||
|
@@ -35,6 +35,8 @@ import "./functions/sizing";
|
||||
import "./functions/smash";
|
||||
import "./functions/sqrt";
|
||||
import "./functions/styling";
|
||||
import "./functions/symbolsOp";
|
||||
import "./functions/symbolsOrd";
|
||||
import "./functions/text";
|
||||
import "./functions/underline";
|
||||
import "./functions/verb";
|
||||
|
52
src/functions/symbolsOp.js
Normal file
52
src/functions/symbolsOp.js
Normal file
@@ -0,0 +1,52 @@
|
||||
// @flow
|
||||
import {defineFunctionBuilders} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type Options from "../Options";
|
||||
import type ParseNode from "../ParseNode";
|
||||
import type {Group} from "../symbols";
|
||||
|
||||
// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js.
|
||||
|
||||
// NOTE: `NODETYPE` is constrained by `Group` instead of `NodeType`. This
|
||||
// guarantees that `group.value` is a string as required by buildCommon.mathsym.
|
||||
function defineOpFunction<NODETYPE: Group>(
|
||||
type: NODETYPE,
|
||||
mathmlNodePostProcessor?: (
|
||||
mathMLTree.MathNode,
|
||||
ParseNode<NODETYPE>,
|
||||
Options) => *,
|
||||
) {
|
||||
defineFunctionBuilders({
|
||||
type,
|
||||
htmlBuilder(group: ParseNode<NODETYPE>, options) {
|
||||
const groupValue: string = group.value;
|
||||
return buildCommon.mathsym(
|
||||
groupValue, group.mode, options, ["m" + type]);
|
||||
},
|
||||
mathmlBuilder(group: ParseNode<NODETYPE>, options) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mo", [mml.makeText(group.value, group.mode)]);
|
||||
if (mathmlNodePostProcessor) {
|
||||
mathmlNodePostProcessor(node, group, options);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
defineOpFunction("bin", (mathNode, group, options) => {
|
||||
const variant = mml.getVariant(group, options);
|
||||
if (variant === "bold-italic") {
|
||||
mathNode.setAttribute("mathvariant", variant);
|
||||
}
|
||||
});
|
||||
defineOpFunction("rel");
|
||||
defineOpFunction("open");
|
||||
defineOpFunction("close");
|
||||
defineOpFunction("inner");
|
||||
defineOpFunction("punct", mathNode => mathNode.setAttribute("separator", "true"));
|
||||
|
63
src/functions/symbolsOrd.js
Normal file
63
src/functions/symbolsOrd.js
Normal file
@@ -0,0 +1,63 @@
|
||||
// @flow
|
||||
import {defineFunctionBuilders} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
|
||||
// src/symbols.js.
|
||||
|
||||
const defaultVariant = {
|
||||
"mi": "italic",
|
||||
"mn": "normal",
|
||||
"mtext": "normal",
|
||||
};
|
||||
|
||||
defineFunctionBuilders({
|
||||
type: "mathord",
|
||||
htmlBuilder(group, options) {
|
||||
return buildCommon.makeOrd(group, options, "mathord");
|
||||
},
|
||||
mathmlBuilder(group, options) {
|
||||
const node = new mathMLTree.MathNode(
|
||||
"mi",
|
||||
[mml.makeText(group.value, group.mode)]);
|
||||
|
||||
const variant = mml.getVariant(group, options) || "italic";
|
||||
if (variant !== defaultVariant[node.type]) {
|
||||
node.setAttribute("mathvariant", variant);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
});
|
||||
|
||||
defineFunctionBuilders({
|
||||
type: "textord",
|
||||
htmlBuilder(group, options) {
|
||||
return buildCommon.makeOrd(group, options, "textord");
|
||||
},
|
||||
mathmlBuilder(group, options) {
|
||||
const text = mml.makeText(group.value, group.mode);
|
||||
|
||||
const variant = mml.getVariant(group, options) || "normal";
|
||||
|
||||
let node;
|
||||
if (group.mode === 'text') {
|
||||
node = new mathMLTree.MathNode("mtext", [text]);
|
||||
} else if (/[0-9]/.test(group.value)) {
|
||||
// TODO(kevinb) merge adjacent <mn> nodes
|
||||
// do it as a post processing step
|
||||
node = new mathMLTree.MathNode("mn", [text]);
|
||||
} else if (group.value === "\\prime") {
|
||||
node = new mathMLTree.MathNode("mo", [text]);
|
||||
} else {
|
||||
node = new mathMLTree.MathNode("mi", [text]);
|
||||
}
|
||||
if (variant !== defaultVariant[node.type]) {
|
||||
node.setAttribute("mathvariant", variant);
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
});
|
@@ -24,7 +24,7 @@ type Font = "main" | "ams"
|
||||
// types for raw text tokens, and we want to avoid conflicts with higher-level
|
||||
// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
|
||||
// looking up the `symbols` map.
|
||||
type Group =
|
||||
export type Group =
|
||||
"accent-token" | "bin" | "close" | "inner" | "mathord" |
|
||||
"op-token" | "open" | "punct" | "rel" | "spacing" | "textord";
|
||||
type CharInfoMap = {[string]: {font: Font, group: Group, replace: ?string}};
|
||||
|
Reference in New Issue
Block a user