mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 11:18:39 +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) {
|
||||
// Superscript and subscripts are handled in the TeXbook on page
|
||||
// 445-446, rules 18(a-f).
|
||||
|
@@ -158,45 +158,6 @@ groupTypes.ordgroup = function(group, options) {
|
||||
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) {
|
||||
// Is the inner group a relevant horizonal brace?
|
||||
let isBrace = false;
|
||||
|
@@ -40,45 +40,9 @@ defineFunction(["\\sqrt"], {
|
||||
};
|
||||
});
|
||||
|
||||
// Non-mathy text, possibly in a font
|
||||
const textFunctionFonts = {
|
||||
"\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf",
|
||||
"\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf",
|
||||
"\\textit": "textit",
|
||||
};
|
||||
import "./functions/color";
|
||||
|
||||
defineFunction([
|
||||
"\\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),
|
||||
};
|
||||
});
|
||||
import "./functions/text";
|
||||
|
||||
// \color is handled in Parser.js's parseImplicitGroup
|
||||
defineFunction(["\\color"], {
|
||||
@@ -185,34 +149,6 @@ const fontAliases = {
|
||||
"\\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} = {
|
||||
"\u222b": "\\int",
|
||||
"\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