mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-07 12:18:39 +00:00
\color affects following \right, put array cells in their own groups (#1845)
* \color affects following \right Fix #1844 by giving `leftright` nodes a `rightColor` attribute for how to color the right bracket. Now `\color` sets the macro `\current@color` in the current environment (in particular, resetting after `\right`), just like `color.sty` does in LaTeX. This is used to specially pass the current color into any following `\right` and then into the `leftright` parse node. * Add test * Put each array cell in its own group/namespace * Improve cell group isolation, add test and TODO * Improve comments
This commit is contained in:
committed by
Kevin Barabash
parent
39da3f5119
commit
19d9d83ad3
@@ -79,6 +79,9 @@ function parseArray(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start group for first cell
|
||||||
|
parser.gullet.beginGroup();
|
||||||
|
|
||||||
let row = [];
|
let row = [];
|
||||||
const body = [row];
|
const body = [row];
|
||||||
const rowGaps = [];
|
const rowGaps = [];
|
||||||
@@ -88,7 +91,11 @@ function parseArray(
|
|||||||
hLinesBeforeRow.push(getHLines(parser));
|
hLinesBeforeRow.push(getHLines(parser));
|
||||||
|
|
||||||
while (true) { // eslint-disable-line no-constant-condition
|
while (true) { // eslint-disable-line no-constant-condition
|
||||||
|
// Parse each cell in its own group (namespace)
|
||||||
let cell = parser.parseExpression(false, "\\cr");
|
let cell = parser.parseExpression(false, "\\cr");
|
||||||
|
parser.gullet.endGroup();
|
||||||
|
parser.gullet.beginGroup();
|
||||||
|
|
||||||
cell = {
|
cell = {
|
||||||
type: "ordgroup",
|
type: "ordgroup",
|
||||||
mode: parser.mode,
|
mode: parser.mode,
|
||||||
@@ -132,7 +139,12 @@ function parseArray(
|
|||||||
parser.nextToken);
|
parser.nextToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// End cell group
|
||||||
parser.gullet.endGroup();
|
parser.gullet.endGroup();
|
||||||
|
// End array group defining \\
|
||||||
|
parser.gullet.endGroup();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "array",
|
type: "array",
|
||||||
mode: parser.mode,
|
mode: parser.mode,
|
||||||
@@ -671,6 +683,7 @@ defineEnvironment({
|
|||||||
body: [res],
|
body: [res],
|
||||||
left: delimiters[0],
|
left: delimiters[0],
|
||||||
right: delimiters[1],
|
right: delimiters[1],
|
||||||
|
rightColor: undefined, // \right uninfluenced by \color in array
|
||||||
} : res;
|
} : res;
|
||||||
},
|
},
|
||||||
htmlBuilder,
|
htmlBuilder,
|
||||||
@@ -775,6 +788,7 @@ defineEnvironment({
|
|||||||
body: [res],
|
body: [res],
|
||||||
left: "\\{",
|
left: "\\{",
|
||||||
right: ".",
|
right: ".",
|
||||||
|
rightColor: undefined,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
htmlBuilder,
|
htmlBuilder,
|
||||||
|
@@ -67,7 +67,13 @@ defineFunction({
|
|||||||
handler({parser, breakOnTokenText}, args) {
|
handler({parser, breakOnTokenText}, args) {
|
||||||
const color = assertNodeType(args[0], "color-token").color;
|
const color = assertNodeType(args[0], "color-token").color;
|
||||||
|
|
||||||
// If we see a styling function, parse out the implicit body
|
// Set macro \current@color in current namespace to store the current
|
||||||
|
// color, mimicking the behavior of color.sty.
|
||||||
|
// This is currently used just to correctly color a \right
|
||||||
|
// that follows a \color command.
|
||||||
|
parser.gullet.macros.set("\\current@color", color);
|
||||||
|
|
||||||
|
// Parse out the implicit body that should be colored.
|
||||||
const body = parser.parseExpression(true, breakOnTokenText);
|
const body = parser.parseExpression(true, breakOnTokenText);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@@ -145,10 +145,16 @@ defineFunction({
|
|||||||
// \left case below triggers parsing of \right in
|
// \left case below triggers parsing of \right in
|
||||||
// `const right = parser.parseFunction();`
|
// `const right = parser.parseFunction();`
|
||||||
// uses this return value.
|
// uses this return value.
|
||||||
|
const color = context.parser.gullet.macros.get("\\current@color");
|
||||||
|
if (color && typeof color !== "string") {
|
||||||
|
throw new ParseError(
|
||||||
|
"\\current@color set to non-string in \\right");
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
type: "leftright-right",
|
type: "leftright-right",
|
||||||
mode: context.parser.mode,
|
mode: context.parser.mode,
|
||||||
delim: checkDelimiter(args[0], context).text,
|
delim: checkDelimiter(args[0], context).text,
|
||||||
|
color, // undefined if not set via \color
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -178,6 +184,7 @@ defineFunction({
|
|||||||
body,
|
body,
|
||||||
left: delim.text,
|
left: delim.text,
|
||||||
right: right.delim,
|
right: right.delim,
|
||||||
|
rightColor: right.color,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
htmlBuilder: (group, options) => {
|
htmlBuilder: (group, options) => {
|
||||||
@@ -241,12 +248,14 @@ defineFunction({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let rightDelim;
|
let rightDelim;
|
||||||
// Same for the right delimiter
|
// Same for the right delimiter, but using color specified by \color
|
||||||
if (group.right === ".") {
|
if (group.right === ".") {
|
||||||
rightDelim = html.makeNullDelimiter(options, ["mclose"]);
|
rightDelim = html.makeNullDelimiter(options, ["mclose"]);
|
||||||
} else {
|
} else {
|
||||||
|
const colorOptions = group.rightColor ?
|
||||||
|
options.withColor(group.rightColor) : options;
|
||||||
rightDelim = delimiter.leftRightDelim(
|
rightDelim = delimiter.leftRightDelim(
|
||||||
group.right, innerHeight, innerDepth, options,
|
group.right, innerHeight, innerDepth, colorOptions,
|
||||||
group.mode, ["mclose"]);
|
group.mode, ["mclose"]);
|
||||||
}
|
}
|
||||||
// Add it to the end of the expression.
|
// Add it to the end of the expression.
|
||||||
@@ -273,6 +282,10 @@ defineFunction({
|
|||||||
|
|
||||||
rightNode.setAttribute("fence", "true");
|
rightNode.setAttribute("fence", "true");
|
||||||
|
|
||||||
|
if (group.rightColor) {
|
||||||
|
rightNode.setAttribute("mathcolor", group.rightColor);
|
||||||
|
}
|
||||||
|
|
||||||
inner.push(rightNode);
|
inner.push(rightNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -318,12 +318,14 @@ type ParseNodeTypes = {
|
|||||||
body: AnyParseNode[],
|
body: AnyParseNode[],
|
||||||
left: string,
|
left: string,
|
||||||
right: string,
|
right: string,
|
||||||
|
rightColor: ?string, // undefined means "inherit"
|
||||||
|},
|
|},
|
||||||
"leftright-right": {|
|
"leftright-right": {|
|
||||||
type: "leftright-right",
|
type: "leftright-right",
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
loc?: ?SourceLocation,
|
loc?: ?SourceLocation,
|
||||||
delim: string,
|
delim: string,
|
||||||
|
color: ?string, // undefined means "inherit"
|
||||||
|},
|
|},
|
||||||
"mathchoice": {|
|
"mathchoice": {|
|
||||||
type: "mathchoice",
|
type: "mathchoice",
|
||||||
|
@@ -3123,6 +3123,21 @@ describe("A macro expander", function() {
|
|||||||
.toParseLike`11\sqrt[2]{2}11`;
|
.toParseLike`11\sqrt[2]{2}11`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("array cells generate groups", () => {
|
||||||
|
expect`\def\x{1}\begin{matrix}\x&\def\x{2}\x&\x\end{matrix}`
|
||||||
|
.toParseLike`\begin{matrix}1&2&1\end{matrix}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: This doesn't yet work; before the environment gets called,
|
||||||
|
// {matrix} gets consumed which means that the \def gets executed, before
|
||||||
|
// we can create a group. :-( Issue #1989
|
||||||
|
/*
|
||||||
|
it("array cells generate groups", () => {
|
||||||
|
expect`\def\x{1}\begin{matrix}\def\x{2}&\x\end{matrix}`
|
||||||
|
.toParseLike`\begin{matrix}&1\end{matrix}`;
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
it("\\gdef changes settings.macros", () => {
|
it("\\gdef changes settings.macros", () => {
|
||||||
const macros = {};
|
const macros = {};
|
||||||
expect`\gdef\foo{1}`.toParse(new Settings({macros}));
|
expect`\gdef\foo{1}`.toParse(new Settings({macros}));
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 39 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 28 KiB |
@@ -77,7 +77,11 @@ Cases: |
|
|||||||
Colors:
|
Colors:
|
||||||
tex: \blue{a}\textcolor{#0f0}{b}\textcolor{red}{c}
|
tex: \blue{a}\textcolor{#0f0}{b}\textcolor{red}{c}
|
||||||
nolatex: different syntax and different scope
|
nolatex: different syntax and different scope
|
||||||
ColorImplicit: bl{ack\color{red}red\textcolor{green}{green}red\color{blue}blue}black
|
ColorImplicit:
|
||||||
|
\begin{array}{l}
|
||||||
|
bl{ack\color{red}red\textcolor{green}{green}red\color{blue}blue}black \\
|
||||||
|
black\left(black\color{red}red\right)black
|
||||||
|
\end{array}
|
||||||
ColorSpacing: \textcolor{red}{\displaystyle \int x} + 1
|
ColorSpacing: \textcolor{red}{\displaystyle \int x} + 1
|
||||||
Colorbox: a \colorbox{teal} B \fcolorbox{blue}{red}{C} e+\colorbox{teal}x
|
Colorbox: a \colorbox{teal} B \fcolorbox{blue}{red}{C} e+\colorbox{teal}x
|
||||||
DashesAndQuotes: |
|
DashesAndQuotes: |
|
||||||
|
Reference in New Issue
Block a user