Skip to content

Commit

Permalink
Merge pull request #1060 from mathjax/issue3184
Browse files Browse the repository at this point in the history
Fix handling of _ and ^ followed by command that doesn't push content (mathjax/MathJax#3184)
  • Loading branch information
dpvc committed Mar 16, 2024
2 parents dcef69d + d1a0907 commit 119fb6b
Show file tree
Hide file tree
Showing 13 changed files with 54 additions and 15 deletions.
4 changes: 3 additions & 1 deletion ts/input/tex/Stack.ts
Expand Up @@ -99,7 +99,9 @@ export default class Stack {
this.Push(...top);
continue;
}
this.stack.push(item);
if (!item.isKind('null')) {
this.stack.push(item);
}
if (item.env) {
if (item.copyEnv) {
Object.assign(item.env, this.env);
Expand Down
2 changes: 1 addition & 1 deletion ts/input/tex/StackItem.ts
Expand Up @@ -414,7 +414,7 @@ export abstract class BaseItem extends MmlStack implements StackItem {
/**
* @return {string} The type of the stack item.
*/
public get kind(): string {
public get kind(): string {
return 'base';
}

Expand Down
25 changes: 15 additions & 10 deletions ts/input/tex/TexParser.ts
Expand Up @@ -570,11 +570,13 @@ export default class TexParser {
}
// These are the cases to handle sub and superscripts.
if (node.attributes.get(TexConstant.Attr.LATEX) === '^' &&
str !== '^' && str !== '\\^') {
if (str === '}') {
this.composeBraces(node.childNodes[2]);
} else {
node.childNodes[2].attributes.set(TexConstant.Attr.LATEX, str);
str !== '^' && str !== '\\^') {
if (node.childNodes[2]) {
if (str === '}') {
this.composeBraces(node.childNodes[2]);
} else {
node.childNodes[2].attributes.set(TexConstant.Attr.LATEX, str);
}
}
if (node.childNodes[1]) {
const sub = node.childNodes[1].attributes.get(TexConstant.Attr.LATEX);
Expand All @@ -585,11 +587,13 @@ export default class TexParser {
return;
}
if (node.attributes.get(TexConstant.Attr.LATEX) === '_' &&
str !== '_' && str !== '\\_') {
if (str === '}') {
this.composeBraces(node.childNodes[1]);
} else {
node.childNodes[1].attributes.set(TexConstant.Attr.LATEX, str);
str !== '_' && str !== '\\_') {
if (node.childNodes[1]) {
if (str === '}') {
this.composeBraces(node.childNodes[1]);
} else {
node.childNodes[1].attributes.set(TexConstant.Attr.LATEX, str);
}
}
if (node.childNodes[2]) {
const sub = node.childNodes[2].attributes.get(TexConstant.Attr.LATEX);
Expand All @@ -616,6 +620,7 @@ export default class TexParser {
*/
private composeLatex(
node: MmlNode, comp: string, pos1: number, pos2: number) {
if (!node.childNodes[pos1] || !node.childNodes[pos2]) return;
const expr = node.childNodes[pos1].attributes.get(TexConstant.Attr.LATEX) + comp +
node.childNodes[pos2].attributes.get(TexConstant.Attr.LATEX);
node.attributes.set(TexConstant.Attr.LATEX, expr);
Expand Down
2 changes: 2 additions & 0 deletions ts/input/tex/ams/AmsMethods.ts
Expand Up @@ -220,6 +220,7 @@ AmsMethods.HandleDeclareOp = function (parser: TexParser, name: string) {
let op = parser.GetArgument(name);
(parser.configuration.handlers.retrieve(NEW_OPS) as CommandMap).
add(cs, new Macro(cs, AmsMethods.Macro, [`\\operatorname${star}{${op}}`]));
parser.Push(parser.itemFactory.create('null'));
};


Expand Down Expand Up @@ -586,6 +587,7 @@ AmsMethods.HandleTag = function(parser: TexParser, name: string) {
let star = parser.GetStar();
let tagId = ParseUtil.trimSpaces(parser.GetArgument(name));
parser.tags.tag(tagId, star);
parser.Push(parser.itemFactory.create('null'));
};


Expand Down
1 change: 1 addition & 0 deletions ts/input/tex/base/BaseConfiguration.ts
Expand Up @@ -168,6 +168,7 @@ export const BaseConfiguration: Configuration = Configuration.create(
[bitem.StopItem.prototype.kind]: bitem.StopItem,
[bitem.OpenItem.prototype.kind]: bitem.OpenItem,
[bitem.CloseItem.prototype.kind]: bitem.CloseItem,
[bitem.NullItem.prototype.kind]: bitem.NullItem,
[bitem.PrimeItem.prototype.kind]: bitem.PrimeItem,
[bitem.SubsupItem.prototype.kind]: bitem.SubsupItem,
[bitem.OverItem.prototype.kind]: bitem.OverItem,
Expand Down
12 changes: 12 additions & 0 deletions ts/input/tex/base/BaseItems.ts
Expand Up @@ -176,6 +176,18 @@ export class CloseItem extends BaseItem {

}

/**
* Item pushed when a macro doesn't produce any output.
*/
export class NullItem extends BaseItem {
/**
* @override
*/
public get kind() {
return 'null';
}
}


/**
* Item indicating an we are currently dealing with a prime mark.
Expand Down
8 changes: 5 additions & 3 deletions ts/input/tex/base/BaseMethods.ts
Expand Up @@ -268,8 +268,7 @@ BaseMethods.Prime = function(parser: TexParser, c: string) {
} while (c === '\'' || c === entities.rsquo);
sup = ['', '\u2032', '\u2033', '\u2034', '\u2057'][sup.length] || sup;
const node = parser.create('token', 'mo', {variantForm: true}, sup);
parser.Push(
parser.itemFactory.create('prime', base, node) );
parser.Push(parser.itemFactory.create('prime', base, node));
};


Expand Down Expand Up @@ -327,6 +326,7 @@ BaseMethods.MathFont = function(parser: TexParser, name: string, variant: string
*/
BaseMethods.SetFont = function(parser: TexParser, _name: string, font: string) {
parser.stack.env['font'] = font;
parser.Push(parser.itemFactory.create('null'));
};

/**
Expand Down Expand Up @@ -811,6 +811,7 @@ BaseMethods.VBox = function(parser: TexParser, name: string, align: string) {
BaseMethods.Hsize = function (parser: TexParser, name: string) {
parser.GetNext() === '=' && parser.i++;
parser.stack.env.hsize = parser.GetDimen(name);
parser.Push(parser.itemFactory.create('null'));
};

/**
Expand Down Expand Up @@ -1538,10 +1539,11 @@ BaseMethods.NewColumnType = function (parser: TexParser, name: string) {
throw new TexError('BadColumnName', 'Column specifier must be exactly one character: %1', c);
}
if (!n.match(/^\d+$/)) {
throw new TexError('PositiveIntegerArg', 'Argument to %1 must me a positive integer', n);
throw new TexError('PositiveIntegerArg', 'Argument to %1 must be a positive integer', n);
}
const cparser = parser.configuration.columnParser;
cparser.columnHandler[c] = (state: ColumnState) => cparser.macroColumn(state, macro, parseInt(n));
parser.Push(parser.itemFactory.create('null'));
}


Expand Down
1 change: 1 addition & 0 deletions ts/input/tex/color/ColorMethods.ts
Expand Up @@ -112,6 +112,7 @@ ColorMethods.DefineColor = function (parser: TexParser, name: string) {

const colorModel: ColorModel = parser.configuration.packageData.get('color').model;
colorModel.defineColor(model, cname, def);
parser.Push(parser.itemFactory.create('null'));
};

/**
Expand Down
1 change: 1 addition & 0 deletions ts/input/tex/extpfeil/ExtpfeilConfiguration.ts
Expand Up @@ -67,6 +67,7 @@ ExtpfeilMethods.NewExtArrow = function(parser: TexParser, name: string) {
let spaces = space.split(',');
NewcommandUtil.addMacro(parser, cs, ExtpfeilMethods.xArrow,
[parseInt(chr), parseInt(spaces[0]), parseInt(spaces[1])]);
parser.Push(parser.itemFactory.create('null'));
};


Expand Down
7 changes: 7 additions & 0 deletions ts/input/tex/mathtools/MathtoolsMethods.ts
Expand Up @@ -516,6 +516,7 @@ export const MathtoolsMethods: Record<string, ParseMethod> = {
const open = parser.GetArgument(name);
const close = parser.GetArgument(name);
MathtoolsUtil.addPairedDelims(parser.configuration, cs, [open, close]);
parser.Push(parser.itemFactory.create('null'));
},

/**
Expand All @@ -531,6 +532,7 @@ export const MathtoolsMethods: Record<string, ParseMethod> = {
const close = parser.GetArgument(name);
const body = parser.GetArgument(name);
MathtoolsUtil.addPairedDelims(parser.configuration, cs, [open, close, body, n]);
parser.Push(parser.itemFactory.create('null'));
},

/**
Expand All @@ -548,6 +550,7 @@ export const MathtoolsMethods: Record<string, ParseMethod> = {
const post = parser.GetArgument(name);
const body = parser.GetArgument(name);
MathtoolsUtil.addPairedDelims(parser.configuration, cs, [open, close, body, n, pre, post]);
parser.Push(parser.itemFactory.create('null'));
},

/**
Expand Down Expand Up @@ -711,6 +714,7 @@ export const MathtoolsMethods: Record<string, ParseMethod> = {
throw new TexError('DuplicateTagForm', 'Duplicate tag form: %1', id);
}
tags.mtFormats.set(id, [left, right, format]);
parser.Push(parser.itemFactory.create('null'));
},

/**
Expand All @@ -727,12 +731,14 @@ export const MathtoolsMethods: Record<string, ParseMethod> = {
const id = parser.GetArgument(name).trim();
if (!id) {
tags.mtCurrent = null;
parser.Push(parser.itemFactory.create('null'));
return;
}
if (!tags.mtFormats.has(id)) {
throw new TexError('UndefinedTagForm', 'Undefined tag form: %1', id);
}
tags.mtCurrent = tags.mtFormats.get(id);
parser.Push(parser.itemFactory.create('null'));
},

/**
Expand All @@ -757,6 +763,7 @@ export const MathtoolsMethods: Record<string, ParseMethod> = {
for (const id of Object.keys(keys)) {
options[id] = keys[id];
}
parser.Push(parser.itemFactory.create('null'));
},

/**
Expand Down
4 changes: 4 additions & 0 deletions ts/input/tex/newcommand/NewcommandMethods.ts
Expand Up @@ -49,6 +49,7 @@ NewcommandMethods.NewCommand = function(parser: TexParser, name: string) {
let opt = parser.GetBrackets(name);
let def = parser.GetArgument(name);
NewcommandUtil.addMacro(parser, cs, NewcommandMethods.Macro, [def, n, opt]);
parser.Push(parser.itemFactory.create('null'));
};


Expand All @@ -65,6 +66,7 @@ NewcommandMethods.NewEnvironment = function(parser: TexParser, name: string) {
let bdef = parser.GetArgument(name);
let edef = parser.GetArgument(name);
NewcommandUtil.addEnvironment(parser, env, NewcommandMethods.BeginEnv, [true, bdef, edef, n, opt]);
parser.Push(parser.itemFactory.create('null'));
};


Expand All @@ -83,6 +85,7 @@ NewcommandMethods.MacroDef = function(parser: TexParser, name: string) {
NewcommandUtil.addMacro(parser, cs, NewcommandMethods.Macro, [def, params]) :
// @test Def Let
NewcommandUtil.addMacro(parser, cs, NewcommandMethods.MacroWithTemplate, [def].concat(params));
parser.Push(parser.itemFactory.create('null'));
};


Expand Down Expand Up @@ -112,6 +115,7 @@ NewcommandMethods.Let = function(parser: TexParser, name: string) {
c = parser.GetNext();
}
const handlers = parser.configuration.handlers;
parser.Push(parser.itemFactory.create('null'));
if (c === '\\') {
// @test Let Bar, Let Brace Equal Stretchy
name = NewcommandUtil.GetCSname(parser, name);
Expand Down
1 change: 1 addition & 0 deletions ts/input/tex/require/RequireConfiguration.ts
Expand Up @@ -192,6 +192,7 @@ export const RequireMethods: Record<string, ParseMethod> = {
throw new TexError('BadPackageName', 'Argument for %1 is not a valid package name', name);
}
RequireLoad(parser, required);
parser.Push(parser.itemFactory.create('null'));
}

};
Expand Down
1 change: 1 addition & 0 deletions ts/input/tex/setoptions/SetOptionsConfiguration.ts
Expand Up @@ -113,6 +113,7 @@ const setOptionsMap = new CommandMap('setoptions', {
config.filterValue(parser, extension, key, options[key]);
}
}
parser.Push(parser.itemFactory.create('null'));
}
});

Expand Down

0 comments on commit 119fb6b

Please sign in to comment.