mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
allow sizing commands inside optional groups (#885)
* allow sizing commands inside optional groups * allow color, old font, and style commands inside optional groups
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
"jest": "^20.0.4",
|
||||
"jest-serializer-html": "^4.0.0",
|
||||
"js-yaml": "^3.3.1",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
"jspngopt": "^0.2.0",
|
||||
"less": "~2.7.1",
|
||||
"less-plugin-clean-css": "^1.5.1",
|
||||
|
@@ -203,7 +203,7 @@ export default class Parser {
|
||||
if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
|
||||
break;
|
||||
}
|
||||
const atom = this.parseAtom();
|
||||
const atom = this.parseAtom(breakOnTokenText);
|
||||
if (!atom) {
|
||||
if (!this.settings.throwOnError && lex.text[0] === "\\") {
|
||||
const errorNode = this.handleUnsupportedCmd();
|
||||
@@ -349,12 +349,13 @@ export default class Parser {
|
||||
/**
|
||||
* Parses a group with optional super/subscripts.
|
||||
*
|
||||
* @param {"]" | "}"} breakOnTokenText - character to stop parsing the group on.
|
||||
* @return {?ParseNode}
|
||||
*/
|
||||
parseAtom() {
|
||||
parseAtom(breakOnTokenText) {
|
||||
// The body of an atom is an implicit group, so that things like
|
||||
// \left(x\right)^2 work correctly.
|
||||
const base = this.parseImplicitGroup();
|
||||
const base = this.parseImplicitGroup(breakOnTokenText);
|
||||
|
||||
// In text mode, we don't have superscripts or subscripts
|
||||
if (this.mode === "text") {
|
||||
@@ -466,9 +467,10 @@ export default class Parser {
|
||||
* small text {\Large large text} small text again
|
||||
* It is also used for \left and \right to get the correct grouping.
|
||||
*
|
||||
* @param {"]" | "}"} breakOnTokenText - character to stop parsing the group on.
|
||||
* @return {?ParseNode}
|
||||
*/
|
||||
parseImplicitGroup() {
|
||||
parseImplicitGroup(breakOnTokenText) {
|
||||
const start = this.parseSymbol();
|
||||
|
||||
if (start == null) {
|
||||
@@ -527,7 +529,7 @@ export default class Parser {
|
||||
} else if (utils.contains(Parser.sizeFuncs, func)) {
|
||||
// If we see a sizing function, parse out the implicit body
|
||||
this.consumeSpaces();
|
||||
const body = this.parseExpression(false);
|
||||
const body = this.parseExpression(false, breakOnTokenText);
|
||||
return new ParseNode("sizing", {
|
||||
// Figure out what size to use based on the list of functions above
|
||||
size: utils.indexOf(Parser.sizeFuncs, func) + 1,
|
||||
@@ -536,7 +538,7 @@ export default class Parser {
|
||||
} else if (utils.contains(Parser.styleFuncs, func)) {
|
||||
// If we see a styling function, parse out the implicit body
|
||||
this.consumeSpaces();
|
||||
const body = this.parseExpression(true);
|
||||
const body = this.parseExpression(true, breakOnTokenText);
|
||||
return new ParseNode("styling", {
|
||||
// Figure out what style to use by pulling out the style from
|
||||
// the function name
|
||||
@@ -547,7 +549,7 @@ export default class Parser {
|
||||
const style = Parser.oldFontFuncs[func];
|
||||
// If we see an old font function, parse out the implicit body
|
||||
this.consumeSpaces();
|
||||
const body = this.parseExpression(true);
|
||||
const body = this.parseExpression(true, breakOnTokenText);
|
||||
if (style.slice(0, 4) === 'text') {
|
||||
return new ParseNode("text", {
|
||||
style: style,
|
||||
@@ -565,7 +567,7 @@ export default class Parser {
|
||||
if (!color) {
|
||||
throw new ParseError("\\color not followed by color");
|
||||
}
|
||||
const body = this.parseExpression(true);
|
||||
const body = this.parseExpression(true, breakOnTokenText);
|
||||
return new ParseNode("color", {
|
||||
type: "color",
|
||||
color: color.result.value,
|
||||
@@ -875,7 +877,7 @@ export default class Parser {
|
||||
if (this.nextToken.text === (optional ? "[" : "{")) {
|
||||
// If we get a brace, parse an expression
|
||||
this.consume();
|
||||
const expression = this.parseExpression(false, optional ? "]" : null);
|
||||
const expression = this.parseExpression(false, optional ? "]" : "}");
|
||||
const lastToken = this.nextToken;
|
||||
// Make sure we get a close brace
|
||||
this.expect(optional ? "]" : "}");
|
||||
|
178
test/__snapshots__/katex-spec.js.snap
Normal file
178
test/__snapshots__/katex-spec.js.snap
Normal file
@@ -0,0 +1,178 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`An implicit group parser within optional groups should work style commands \\sqrt[\\textstyle 3]{x} 1`] = `
|
||||
[
|
||||
{
|
||||
"type": "sqrt",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "sqrt",
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"mode": "math",
|
||||
"value": "x"
|
||||
}
|
||||
]
|
||||
},
|
||||
"index": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "styling",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"style": "text",
|
||||
"value": [
|
||||
{
|
||||
"type": "textord",
|
||||
"mode": "math",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`An implicit group parser within optional groups should work with \\color: \\sqrt[\\color{red} 3]{x} 1`] = `
|
||||
[
|
||||
{
|
||||
"type": "sqrt",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "sqrt",
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"mode": "math",
|
||||
"value": "x"
|
||||
}
|
||||
]
|
||||
},
|
||||
"index": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "color",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "color",
|
||||
"color": "red",
|
||||
"value": [
|
||||
{
|
||||
"type": "textord",
|
||||
"mode": "math",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`An implicit group parser within optional groups should work with sizing commands: \\sqrt[\\small 3]{x} 1`] = `
|
||||
[
|
||||
{
|
||||
"type": "sqrt",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "sqrt",
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"mode": "math",
|
||||
"value": "x"
|
||||
}
|
||||
]
|
||||
},
|
||||
"index": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "sizing",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"size": 5,
|
||||
"value": [
|
||||
{
|
||||
"type": "textord",
|
||||
"mode": "math",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`An implicit group parser within optional groups should work wwith old font functions: \\sqrt[\\tt 3]{x} 1`] = `
|
||||
[
|
||||
{
|
||||
"type": "sqrt",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "sqrt",
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "mathord",
|
||||
"mode": "math",
|
||||
"value": "x"
|
||||
}
|
||||
]
|
||||
},
|
||||
"index": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "font",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "textord",
|
||||
"mode": "math",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
},
|
||||
"font": "mathtt"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
`;
|
@@ -3,6 +3,7 @@
|
||||
/* global expect: false */
|
||||
/* global it: false */
|
||||
/* global describe: false */
|
||||
import stringify from 'json-stable-stringify';
|
||||
|
||||
import buildMathML from "../src/buildMathML";
|
||||
import buildTree from "../src/buildTree";
|
||||
@@ -13,6 +14,27 @@ import Options from "../src/Options";
|
||||
import Settings from "../src/Settings";
|
||||
import Style from "../src/Style";
|
||||
|
||||
const typeFirstCompare = (a, b) => {
|
||||
if (a.key === 'type') {
|
||||
return -1;
|
||||
} else if (b.key === 'type') {
|
||||
return 1;
|
||||
} else {
|
||||
return a.key < b.key ? -1 : 1;
|
||||
}
|
||||
};
|
||||
|
||||
const serializer = {
|
||||
print(val) {
|
||||
return stringify(val, {cmp: typeFirstCompare, space: ' '});
|
||||
},
|
||||
test() {
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
expect.addSnapshotSerializer(serializer);
|
||||
|
||||
const defaultSettings = new Settings({});
|
||||
const defaultOptions = new Options({
|
||||
style: Style.TEXT,
|
||||
@@ -520,6 +542,28 @@ describe("An implicit group parser", function() {
|
||||
expect(sizing.type).toEqual("sizing");
|
||||
expect(sizing.value.value.length).toBe(1);
|
||||
});
|
||||
|
||||
describe("within optional groups", () => {
|
||||
it("should work with sizing commands: \\sqrt[\\small 3]{x}", () => {
|
||||
const tree = stripPositions(getParsed("\\sqrt[\\small 3]{x}"));
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should work with \\color: \\sqrt[\\color{red} 3]{x}", () => {
|
||||
const tree = stripPositions(getParsed("\\sqrt[\\color{red} 3]{x}"));
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should work style commands \\sqrt[\\textstyle 3]{x}", () => {
|
||||
const tree = stripPositions(getParsed("\\sqrt[\\textstyle 3]{x}"));
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should work wwith old font functions: \\sqrt[\\tt 3]{x}", () => {
|
||||
const tree = stripPositions(getParsed("\\sqrt[\\tt 3]{x}"));
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("A function parser", function() {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 9.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 9.5 KiB |
@@ -214,7 +214,7 @@ SizingBaseline:
|
||||
pre: x
|
||||
post: M
|
||||
Sizing: |
|
||||
{\Huge x}{\LARGE y}{\normalsize z}{\scriptsize w}
|
||||
{\Huge x}{\LARGE y}{\normalsize z}{\scriptsize w}\sqrt[\small 3]{x+1}
|
||||
Smash: \left( X^{\smash 2} \right) \sqrt{\smash[b]{y}}
|
||||
Spacing: ^3+[-1][1-1]1=1(=1)\lvert a\rvert~b
|
||||
Sqrt: |
|
||||
|
Reference in New Issue
Block a user