mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 11:18:39 +00:00
Support \arraystretch as a macro definition (#1381)
* Support \arraystretch as a macro definition Also add `expandMacro` and `expandMacroAsText` helpers to `MacroExpander`. * Remove excess defaulting * Add test
This commit is contained in:
committed by
Kevin Barabash
parent
563b0d5f8f
commit
fcb32f058b
@@ -249,6 +249,40 @@ export default class MacroExpander implements MacroContextInterface {
|
||||
throw new Error(); // eslint-disable-line no-unreachable
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully expand the given macro name and return the resulting list of
|
||||
* tokens, or return `undefined` if no such macro is defined.
|
||||
*/
|
||||
expandMacro(name: string): Token[] | void {
|
||||
if (!this.macros.get(name)) {
|
||||
return undefined;
|
||||
}
|
||||
const output = [];
|
||||
const oldStackLength = this.stack.length;
|
||||
this.pushToken(new Token(name));
|
||||
while (this.stack.length > oldStackLength) {
|
||||
const expanded = this.expandOnce();
|
||||
// expandOnce returns Token if and only if it's fully expanded.
|
||||
if (expanded instanceof Token) {
|
||||
output.push(this.stack.pop());
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fully expand the given macro name and return the result as a string,
|
||||
* or return `undefined` if no such macro is defined.
|
||||
*/
|
||||
expandMacroAsText(name: string): string | void {
|
||||
const tokens = this.expandMacro(name);
|
||||
if (tokens) {
|
||||
return tokens.map((token) => token.text).join("");
|
||||
} else {
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expanded macro as a reversed array of tokens and a macro
|
||||
* argument count. Or returns `null` if no such macro.
|
||||
|
@@ -25,7 +25,7 @@ type AlignSpec = { type: "separator", separator: string } | {
|
||||
export type ArrayEnvNodeData = {|
|
||||
type: "array",
|
||||
hskipBeforeAndAfter?: boolean,
|
||||
arraystretch?: number,
|
||||
arraystretch: number,
|
||||
addJot?: boolean,
|
||||
cols?: AlignSpec[],
|
||||
body: ParseNode<*>[][], // List of rows in the (2D) array.
|
||||
@@ -71,6 +71,20 @@ function parseArray(
|
||||
parser.gullet.beginGroup();
|
||||
parser.gullet.macros.set("\\\\", "\\cr");
|
||||
|
||||
// Get current arraystretch if it's not set by the environment
|
||||
if (!result.arraystretch) {
|
||||
const arraystretch = parser.gullet.expandMacroAsText("\\arraystretch");
|
||||
if (arraystretch == null) {
|
||||
// Default \arraystretch from lttab.dtx
|
||||
result.arraystretch = 1;
|
||||
} else {
|
||||
result.arraystretch = parseFloat(arraystretch);
|
||||
if (!result.arraystretch || result.arraystretch < 0) {
|
||||
throw new ParseError(`Invalid \\arraystretch: ${arraystretch}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let row = [];
|
||||
const body = [row];
|
||||
const rowGaps = [];
|
||||
@@ -166,10 +180,7 @@ const htmlBuilder = function(group, options) {
|
||||
// Default \jot from ltmath.dtx
|
||||
// TODO(edemaine): allow overriding \jot via \setlength (#687)
|
||||
const jot = 3 * pt;
|
||||
// Default \arraystretch from lttab.dtx
|
||||
// TODO(gagern): may get redefined once we have user-defined macros
|
||||
const arraystretch = utils.deflt(groupValue.arraystretch, 1);
|
||||
const arrayskip = arraystretch * baselineskip;
|
||||
const arrayskip = groupValue.arraystretch * baselineskip;
|
||||
const arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
|
||||
const arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
|
||||
|
||||
@@ -358,7 +369,7 @@ const mathmlBuilder = function(group, options) {
|
||||
}));
|
||||
};
|
||||
|
||||
// Convinient function for aligned and alignedat environments.
|
||||
// Convenience function for aligned and alignedat environments.
|
||||
const alignedHandler = function(context, args) {
|
||||
const cols = [];
|
||||
let res = {
|
||||
|
@@ -38,6 +38,18 @@ export interface MacroContextInterface {
|
||||
*/
|
||||
expandAfterFuture(): Token;
|
||||
|
||||
/**
|
||||
* Fully expand the given macro name and return the resulting list of
|
||||
* tokens, or return `undefined` if no such macro is defined.
|
||||
*/
|
||||
expandMacro(name: string): Token[] | void;
|
||||
|
||||
/**
|
||||
* Fully expand the given macro name and return the result as a string,
|
||||
* or return `undefined` if no such macro is defined.
|
||||
*/
|
||||
expandMacroAsText(name: string): string | void;
|
||||
|
||||
/**
|
||||
* Consume the specified number of arguments from the token stream,
|
||||
* and return the resulting array of arguments.
|
||||
|
@@ -1,5 +1,148 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`A begin/end parser should grab \\arraystretch 1`] = `
|
||||
[
|
||||
{
|
||||
"type": "array",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "array",
|
||||
"arraystretch": 1.5,
|
||||
"body": [
|
||||
[
|
||||
{
|
||||
"type": "styling",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "styling",
|
||||
"style": "text",
|
||||
"value": [
|
||||
{
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"loc": {
|
||||
"end": 37,
|
||||
"lexer": {
|
||||
"input": "\\\\def\\\\arraystretch{1.5}\\\\begin{matrix}a&b\\\\\\\\c&d\\\\end{matrix}",
|
||||
"pos": 56
|
||||
},
|
||||
"start": 36
|
||||
},
|
||||
"mode": "math",
|
||||
"value": "a"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "styling",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "styling",
|
||||
"style": "text",
|
||||
"value": [
|
||||
{
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"loc": {
|
||||
"end": 39,
|
||||
"lexer": {
|
||||
"input": "\\\\def\\\\arraystretch{1.5}\\\\begin{matrix}a&b\\\\\\\\c&d\\\\end{matrix}",
|
||||
"pos": 56
|
||||
},
|
||||
"start": 38
|
||||
},
|
||||
"mode": "math",
|
||||
"value": "b"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"type": "styling",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "styling",
|
||||
"style": "text",
|
||||
"value": [
|
||||
{
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"loc": {
|
||||
"end": 42,
|
||||
"lexer": {
|
||||
"input": "\\\\def\\\\arraystretch{1.5}\\\\begin{matrix}a&b\\\\\\\\c&d\\\\end{matrix}",
|
||||
"pos": 56
|
||||
},
|
||||
"start": 41
|
||||
},
|
||||
"mode": "math",
|
||||
"value": "c"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "styling",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "styling",
|
||||
"style": "text",
|
||||
"value": [
|
||||
{
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"loc": {
|
||||
"end": 44,
|
||||
"lexer": {
|
||||
"input": "\\\\def\\\\arraystretch{1.5}\\\\begin{matrix}a&b\\\\\\\\c&d\\\\end{matrix}",
|
||||
"pos": 56
|
||||
},
|
||||
"start": 43
|
||||
},
|
||||
"mode": "math",
|
||||
"value": "d"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"hskipBeforeAndAfter": false,
|
||||
"numHLinesBeforeRow": [
|
||||
0,
|
||||
0
|
||||
],
|
||||
"rowGaps": [
|
||||
null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`A parser that does not throw on unsupported commands should build katex-error span for other type of KaTeX error 1`] = `
|
||||
{
|
||||
"attributes": {
|
||||
|
@@ -1173,6 +1173,12 @@ describe("A begin/end parser", function() {
|
||||
const m3 = getParsed("\\begin{matrix}a&b\\\\ c&d \\\\ \\end{matrix}")[0];
|
||||
expect(m3.value.body.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should grab \\arraystretch", function() {
|
||||
const parse = getParsed("\\def\\arraystretch{1.5}" +
|
||||
"\\begin{matrix}a&b\\\\c&d\\end{matrix}");
|
||||
expect(parse).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe("A sqrt parser", function() {
|
||||
|
Reference in New Issue
Block a user