diff --git a/ts/input/tex/ParseUtil.ts b/ts/input/tex/ParseUtil.ts index eff13b609..9ec8ecc15 100644 --- a/ts/input/tex/ParseUtil.ts +++ b/ts/input/tex/ParseUtil.ts @@ -121,7 +121,7 @@ namespace ParseUtil { * @param {string=} big Bigg command. */ export function fenced(configuration: ParseOptions, open: string, mml: MmlNode, - close: string, big: string = '') { + close: string, big: string = '', color: string = '') { // @test Fenced, Fenced3 let nf = configuration.nodeFactory; let mrow = nf.create('node', 'mrow', [], @@ -144,6 +144,7 @@ namespace ParseUtil { {fence: true, stretchy: true, symmetric: true, texClass: TEXCLASS.CLOSE}, closeNode); } + color && mo.attributes.set('mathcolor', color); NodeUtil.appendChildren(mrow, [mo]); return mrow; } diff --git a/ts/input/tex/StackItem.ts b/ts/input/tex/StackItem.ts index 42902123f..084dea098 100644 --- a/ts/input/tex/StackItem.ts +++ b/ts/input/tex/StackItem.ts @@ -353,7 +353,8 @@ export abstract class BaseItem extends MmlStack implements StackItem { // @test ExtraCloseMissingOpen close: ['ExtraCloseMissingOpen', 'Extra close brace or missing open brace'], // @test MissingLeftExtraRight - right: ['MissingLeftExtraRight', 'Missing \\left or extra \\right'] + right: ['MissingLeftExtraRight', 'Missing \\left or extra \\right'], + middle: ['ExtraMiddle', 'Extra \\middle'] }; diff --git a/ts/input/tex/base/BaseConfiguration.ts b/ts/input/tex/base/BaseConfiguration.ts index 5a683c9c8..27b8de74b 100644 --- a/ts/input/tex/base/BaseConfiguration.ts +++ b/ts/input/tex/base/BaseConfiguration.ts @@ -122,6 +122,7 @@ export const BaseConfiguration: Configuration = Configuration.create( [bitem.SubsupItem.prototype.kind]: bitem.SubsupItem, [bitem.OverItem.prototype.kind]: bitem.OverItem, [bitem.LeftItem.prototype.kind]: bitem.LeftItem, + [bitem.Middle.prototype.kind]: bitem.Middle, [bitem.RightItem.prototype.kind]: bitem.RightItem, [bitem.BeginItem.prototype.kind]: bitem.BeginItem, [bitem.EndItem.prototype.kind]: bitem.EndItem, diff --git a/ts/input/tex/base/BaseItems.ts b/ts/input/tex/base/BaseItems.ts index b28504430..f4f8ba42c 100644 --- a/ts/input/tex/base/BaseItems.ts +++ b/ts/input/tex/base/BaseItems.ts @@ -152,7 +152,7 @@ export class OpenItem extends BaseItem { /** - * Item indicating an close brace. Collapses stack until an OpenItem is found. + * Item indicating a close brace. Collapses stack until an OpenItem is found. */ export class CloseItem extends BaseItem { @@ -359,9 +359,9 @@ export class LeftItem extends BaseItem { /** * @override */ - constructor(factory: StackItemFactory) { + constructor(factory: StackItemFactory, delim: string) { super(factory); - this.setProperty('delim', '('); + this.setProperty('delim', delim); } /** @@ -386,16 +386,66 @@ export class LeftItem extends BaseItem { public checkItem(item: StackItem): CheckType { // @test Missing Right if (item.isKind('right')) { + // + // Create the fenced structure as an mrow + // return [[this.factory.create('mml', ParseUtil.fenced( this.factory.configuration, this.getProperty('delim') as string, this.toMml(), - item.getProperty('delim') as string))], true]; + item.getProperty('delim') as string, '', item.getProperty('color') as string))], true]; + } + if (item.isKind('middle')) { + // + // Add the middle delimiter, with empty open and close elements around it for spacing + // + const def = {stretchy: true} as any; + if (item.getProperty('color')) { + def.mathcolor = item.getProperty('color'); + } + this.Push( + this.create('node', 'TeXAtom', [], {texClass: TEXCLASS.CLOSE}), + this.create('token', 'mo', def, item.getProperty('delim')), + this.create('node', 'TeXAtom', [], {texClass: TEXCLASS.OPEN}) + ); + this.env = {}; // Since \middle closes the group, clear the environment + return [[this], true]; // this will reset the environment to its initial state } return super.checkItem(item); } } +/** + * Item pushed when a \\middle delimiter has been found. Stack is + * collapsed until a corresponding LeftItem is encountered. + */ +export class Middle extends BaseItem { + + /** + * @override + */ + constructor(factory: StackItemFactory, delim: string, color: string) { + super(factory); + this.setProperty('delim', delim); + color && this.setProperty('color', color); + } + + /** + * @override + */ + public get kind() { + return 'middle'; + } + + + /** + * @override + */ + get isClose() { + return true; + } + +} /** * Item pushed when a \\right closing delimiter has been found. Stack is @@ -406,9 +456,10 @@ export class RightItem extends BaseItem { /** * @override */ - constructor(factory: StackItemFactory) { + constructor(factory: StackItemFactory, delim: string, color: string) { super(factory); - this.setProperty('delim', ')'); + this.setProperty('delim', delim); + color && this.setProperty('color', color); } /** diff --git a/ts/input/tex/base/BaseMappings.ts b/ts/input/tex/base/BaseMappings.ts index d39f4ac54..11cda06dc 100644 --- a/ts/input/tex/base/BaseMappings.ts +++ b/ts/input/tex/base/BaseMappings.ts @@ -491,7 +491,7 @@ new sm.CommandMap('macros', { left: 'LeftRight', right: 'LeftRight', - middle: 'Middle', + middle: 'LeftRight', llap: 'Lap', rlap: 'Lap', diff --git a/ts/input/tex/base/BaseMethods.ts b/ts/input/tex/base/BaseMethods.ts index 4d5cd39f3..fd7e69e85 100644 --- a/ts/input/tex/base/BaseMethods.ts +++ b/ts/input/tex/base/BaseMethods.ts @@ -335,30 +335,7 @@ BaseMethods.Spacer = function(parser: TexParser, _name: string, space: number) { BaseMethods.LeftRight = function(parser: TexParser, name: string) { // @test Fenced, Fenced3 const first = name.substr(1); - parser.Push( - parser.itemFactory.create(first) - .setProperty('delim', parser.GetDelimiter(name))); -}; - -/** - * Parses middle fenced expressions. - * @param {TexParser} parser The calling parser. - * @param {string} name The macro name. - */ -BaseMethods.Middle = function(parser: TexParser, name: string) { - // @test Middle - const delim = parser.GetDelimiter(name); - let node = parser.create('node', 'TeXAtom', [], {texClass: TEXCLASS.CLOSE}); - parser.Push(node); - if (!parser.stack.Top().isKind('left')) { - // @test Orphan Middle, Middle with Right - throw new TexError('MisplacedMiddle', - '%1 must be within \\left and \\right', parser.currentCS); - } - node = parser.create('token', 'mo', {stretchy: true}, delim); - parser.Push(node); - node = parser.create('node', 'TeXAtom', [], {texClass: TEXCLASS.OPEN}); - parser.Push(node); + parser.Push(parser.itemFactory.create(first, parser.GetDelimiter(name), parser.stack.env.color)); }; /**