mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-08 04:28:41 +00:00
extract color and text commands into their own files in functions sub-directory (#998)
This commit is contained in:
@@ -305,28 +305,6 @@ groupTypes.ordgroup = function(group, options) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
groupTypes.text = function(group, options) {
|
|
||||||
const newOptions = options.withFont(group.value.font);
|
|
||||||
const inner = buildExpression(group.value.body, newOptions, true);
|
|
||||||
buildCommon.tryCombineChars(inner);
|
|
||||||
return makeSpan(["mord", "text"],
|
|
||||||
inner, newOptions);
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.color = function(group, options) {
|
|
||||||
const elements = buildExpression(
|
|
||||||
group.value.value,
|
|
||||||
options.withColor(group.value.color),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
// \color isn't supposed to affect the type of the elements it contains.
|
|
||||||
// To accomplish this, we wrap the results in a fragment, so the inner
|
|
||||||
// elements will be able to directly interact with their neighbors. For
|
|
||||||
// example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
|
|
||||||
return new buildCommon.makeFragment(elements);
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.supsub = function(group, options) {
|
groupTypes.supsub = function(group, options) {
|
||||||
// Superscript and subscripts are handled in the TeXbook on page
|
// Superscript and subscripts are handled in the TeXbook on page
|
||||||
// 445-446, rules 18(a-f).
|
// 445-446, rules 18(a-f).
|
||||||
|
@@ -158,45 +158,6 @@ groupTypes.ordgroup = function(group, options) {
|
|||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
groupTypes.text = function(group, options) {
|
|
||||||
const body = group.value.body;
|
|
||||||
|
|
||||||
// Convert each element of the body into MathML, and combine consecutive
|
|
||||||
// <mtext> outputs into a single <mtext> tag. In this way, we don't
|
|
||||||
// nest non-text items (e.g., $nested-math$) within an <mtext>.
|
|
||||||
const inner = [];
|
|
||||||
let currentText = null;
|
|
||||||
for (let i = 0; i < body.length; i++) {
|
|
||||||
const group = buildGroup(body[i], options);
|
|
||||||
if (group.type === 'mtext' && currentText != null) {
|
|
||||||
Array.prototype.push.apply(currentText.children, group.children);
|
|
||||||
} else {
|
|
||||||
inner.push(group);
|
|
||||||
if (group.type === 'mtext') {
|
|
||||||
currentText = group;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a single tag in the end (presumably <mtext>),
|
|
||||||
// just return it. Otherwise, wrap them in an <mrow>.
|
|
||||||
if (inner.length === 1) {
|
|
||||||
return inner[0];
|
|
||||||
} else {
|
|
||||||
return new mathMLTree.MathNode("mrow", inner);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.color = function(group, options) {
|
|
||||||
const inner = buildExpression(group.value.value, options);
|
|
||||||
|
|
||||||
const node = new mathMLTree.MathNode("mstyle", inner);
|
|
||||||
|
|
||||||
node.setAttribute("mathcolor", group.value.color);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
};
|
|
||||||
|
|
||||||
groupTypes.supsub = function(group, options) {
|
groupTypes.supsub = function(group, options) {
|
||||||
// Is the inner group a relevant horizonal brace?
|
// Is the inner group a relevant horizonal brace?
|
||||||
let isBrace = false;
|
let isBrace = false;
|
||||||
|
@@ -40,45 +40,9 @@ defineFunction(["\\sqrt"], {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Non-mathy text, possibly in a font
|
import "./functions/color";
|
||||||
const textFunctionFonts = {
|
|
||||||
"\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf",
|
|
||||||
"\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf",
|
|
||||||
"\\textit": "textit",
|
|
||||||
};
|
|
||||||
|
|
||||||
defineFunction([
|
import "./functions/text";
|
||||||
"\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal",
|
|
||||||
"\\textbf", "\\textit",
|
|
||||||
], {
|
|
||||||
numArgs: 1,
|
|
||||||
argTypes: ["text"],
|
|
||||||
greediness: 2,
|
|
||||||
allowedInText: true,
|
|
||||||
}, function(context, args) {
|
|
||||||
const body = args[0];
|
|
||||||
return {
|
|
||||||
type: "text",
|
|
||||||
body: ordargument(body),
|
|
||||||
font: textFunctionFonts[context.funcName],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// A two-argument custom color
|
|
||||||
defineFunction(["\\textcolor"], {
|
|
||||||
numArgs: 2,
|
|
||||||
allowedInText: true,
|
|
||||||
greediness: 3,
|
|
||||||
argTypes: ["color", "original"],
|
|
||||||
}, function(context, args) {
|
|
||||||
const color = args[0];
|
|
||||||
const body = args[1];
|
|
||||||
return {
|
|
||||||
type: "color",
|
|
||||||
color: color.value,
|
|
||||||
value: ordargument(body),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// \color is handled in Parser.js's parseImplicitGroup
|
// \color is handled in Parser.js's parseImplicitGroup
|
||||||
defineFunction(["\\color"], {
|
defineFunction(["\\color"], {
|
||||||
@@ -185,34 +149,6 @@ const fontAliases = {
|
|||||||
"\\frak": "\\mathfrak",
|
"\\frak": "\\mathfrak",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Single-argument color functions
|
|
||||||
defineFunction([
|
|
||||||
"\\blue", "\\orange", "\\pink", "\\red",
|
|
||||||
"\\green", "\\gray", "\\purple",
|
|
||||||
"\\blueA", "\\blueB", "\\blueC", "\\blueD", "\\blueE",
|
|
||||||
"\\tealA", "\\tealB", "\\tealC", "\\tealD", "\\tealE",
|
|
||||||
"\\greenA", "\\greenB", "\\greenC", "\\greenD", "\\greenE",
|
|
||||||
"\\goldA", "\\goldB", "\\goldC", "\\goldD", "\\goldE",
|
|
||||||
"\\redA", "\\redB", "\\redC", "\\redD", "\\redE",
|
|
||||||
"\\maroonA", "\\maroonB", "\\maroonC", "\\maroonD", "\\maroonE",
|
|
||||||
"\\purpleA", "\\purpleB", "\\purpleC", "\\purpleD", "\\purpleE",
|
|
||||||
"\\mintA", "\\mintB", "\\mintC",
|
|
||||||
"\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE",
|
|
||||||
"\\grayF", "\\grayG", "\\grayH", "\\grayI",
|
|
||||||
"\\kaBlue", "\\kaGreen",
|
|
||||||
], {
|
|
||||||
numArgs: 1,
|
|
||||||
allowedInText: true,
|
|
||||||
greediness: 3,
|
|
||||||
}, function(context, args) {
|
|
||||||
const body = args[0];
|
|
||||||
return {
|
|
||||||
type: "color",
|
|
||||||
color: "katex-" + context.funcName.slice(1),
|
|
||||||
value: ordargument(body),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const singleCharIntegrals: {[string]: string} = {
|
const singleCharIntegrals: {[string]: string} = {
|
||||||
"\u222b": "\\int",
|
"\u222b": "\\int",
|
||||||
"\u222c": "\\iint",
|
"\u222c": "\\iint",
|
||||||
|
88
src/functions/color.js
Normal file
88
src/functions/color.js
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// @flow
|
||||||
|
import defineFunction, {ordargument} from "../defineFunction";
|
||||||
|
import buildCommon from "../buildCommon";
|
||||||
|
import mathMLTree from "../mathMLTree";
|
||||||
|
|
||||||
|
import * as html from "../buildHTML";
|
||||||
|
import * as mml from "../buildMathML";
|
||||||
|
|
||||||
|
const htmlBuilder = (group, options) => {
|
||||||
|
const elements = html.buildExpression(
|
||||||
|
group.value.value,
|
||||||
|
options.withColor(group.value.color),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
// \color isn't supposed to affect the type of the elements it contains.
|
||||||
|
// To accomplish this, we wrap the results in a fragment, so the inner
|
||||||
|
// elements will be able to directly interact with their neighbors. For
|
||||||
|
// example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
|
||||||
|
return new buildCommon.makeFragment(elements);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mathmlBuilder = (group, options) => {
|
||||||
|
const inner = mml.buildExpression(group.value.value, options);
|
||||||
|
|
||||||
|
const node = new mathMLTree.MathNode("mstyle", inner);
|
||||||
|
|
||||||
|
node.setAttribute("mathcolor", group.value.color);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
defineFunction({
|
||||||
|
type: "color",
|
||||||
|
names: ["\\textcolor"],
|
||||||
|
props: {
|
||||||
|
numArgs: 2,
|
||||||
|
allowedInText: true,
|
||||||
|
greediness: 3,
|
||||||
|
argTypes: ["color", "original"],
|
||||||
|
},
|
||||||
|
handler(context, args) {
|
||||||
|
const color = args[0];
|
||||||
|
const body = args[1];
|
||||||
|
return {
|
||||||
|
type: "color",
|
||||||
|
color: color.value,
|
||||||
|
value: ordargument(body),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
htmlBuilder,
|
||||||
|
mathmlBuilder,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO(kevinb): define these using macros
|
||||||
|
defineFunction({
|
||||||
|
type: "color",
|
||||||
|
names: [
|
||||||
|
"\\blue", "\\orange", "\\pink", "\\red",
|
||||||
|
"\\green", "\\gray", "\\purple",
|
||||||
|
"\\blueA", "\\blueB", "\\blueC", "\\blueD", "\\blueE",
|
||||||
|
"\\tealA", "\\tealB", "\\tealC", "\\tealD", "\\tealE",
|
||||||
|
"\\greenA", "\\greenB", "\\greenC", "\\greenD", "\\greenE",
|
||||||
|
"\\goldA", "\\goldB", "\\goldC", "\\goldD", "\\goldE",
|
||||||
|
"\\redA", "\\redB", "\\redC", "\\redD", "\\redE",
|
||||||
|
"\\maroonA", "\\maroonB", "\\maroonC", "\\maroonD", "\\maroonE",
|
||||||
|
"\\purpleA", "\\purpleB", "\\purpleC", "\\purpleD", "\\purpleE",
|
||||||
|
"\\mintA", "\\mintB", "\\mintC",
|
||||||
|
"\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE",
|
||||||
|
"\\grayF", "\\grayG", "\\grayH", "\\grayI",
|
||||||
|
"\\kaBlue", "\\kaGreen",
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
numArgs: 1,
|
||||||
|
allowedInText: true,
|
||||||
|
greediness: 3,
|
||||||
|
},
|
||||||
|
handler(context, args) {
|
||||||
|
const body = args[0];
|
||||||
|
return {
|
||||||
|
type: "color",
|
||||||
|
color: "katex-" + context.funcName.slice(1),
|
||||||
|
value: ordargument(body),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
htmlBuilder,
|
||||||
|
mathmlBuilder,
|
||||||
|
});
|
71
src/functions/text.js
Normal file
71
src/functions/text.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// @flow
|
||||||
|
import defineFunction, {ordargument} from "../defineFunction";
|
||||||
|
import buildCommon from "../buildCommon";
|
||||||
|
import mathMLTree from "../mathMLTree";
|
||||||
|
|
||||||
|
import * as html from "../buildHTML";
|
||||||
|
import * as mml from "../buildMathML";
|
||||||
|
|
||||||
|
// Non-mathy text, possibly in a font
|
||||||
|
const textFunctionFonts = {
|
||||||
|
"\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf",
|
||||||
|
"\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf",
|
||||||
|
"\\textit": "textit",
|
||||||
|
};
|
||||||
|
|
||||||
|
defineFunction({
|
||||||
|
type: "text",
|
||||||
|
names: [
|
||||||
|
"\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal",
|
||||||
|
"\\textbf", "\\textit",
|
||||||
|
],
|
||||||
|
props: {
|
||||||
|
numArgs: 1,
|
||||||
|
argTypes: ["text"],
|
||||||
|
greediness: 2,
|
||||||
|
allowedInText: true,
|
||||||
|
},
|
||||||
|
handler(context, args) {
|
||||||
|
const body = args[0];
|
||||||
|
return {
|
||||||
|
type: "text",
|
||||||
|
body: ordargument(body),
|
||||||
|
font: textFunctionFonts[context.funcName],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
htmlBuilder(group, options) {
|
||||||
|
const newOptions = options.withFont(group.value.font);
|
||||||
|
const inner = html.buildExpression(group.value.body, newOptions, true);
|
||||||
|
buildCommon.tryCombineChars(inner);
|
||||||
|
return buildCommon.makeSpan(["mord", "text"],
|
||||||
|
inner, newOptions);
|
||||||
|
},
|
||||||
|
mathmlBuilder(group, options) {
|
||||||
|
const body = group.value.body;
|
||||||
|
|
||||||
|
// Convert each element of the body into MathML, and combine consecutive
|
||||||
|
// <mtext> outputs into a single <mtext> tag. In this way, we don't
|
||||||
|
// nest non-text items (e.g., $nested-math$) within an <mtext>.
|
||||||
|
const inner = [];
|
||||||
|
let currentText = null;
|
||||||
|
for (let i = 0; i < body.length; i++) {
|
||||||
|
const group = mml.buildGroup(body[i], options);
|
||||||
|
if (group.type === 'mtext' && currentText != null) {
|
||||||
|
Array.prototype.push.apply(currentText.children, group.children);
|
||||||
|
} else {
|
||||||
|
inner.push(group);
|
||||||
|
if (group.type === 'mtext') {
|
||||||
|
currentText = group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a single tag in the end (presumably <mtext>),
|
||||||
|
// just return it. Otherwise, wrap them in an <mrow>.
|
||||||
|
if (inner.length === 1) {
|
||||||
|
return inner[0];
|
||||||
|
} else {
|
||||||
|
return new mathMLTree.MathNode("mrow", inner);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
Reference in New Issue
Block a user