feat: add nested mtable use case and fix matrix logic

This commit is contained in:
Alexandre Nunes 2020-09-20 15:48:15 -03:00
parent 059880a354
commit dd49c00bc0
4 changed files with 300 additions and 24 deletions

View File

@ -397,6 +397,228 @@ export const mfencedAsPartialFunction = `
</root>
`;
export const mfencedWithNestedMtables = `
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
<mfenced separators="|">
<mrow>
<mtable>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mn>11</mn>
</mrow>
</msub>
</mtd>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mn>12</mn>
</mrow>
</msub>
</mtd>
</mtr>
</mtable>
</mtd>
<mtd>
<mtable>
<mtr>
<mtd>
<mo></mo>
</mtd>
<mtd>
<mo></mo>
</mtd>
</mtr>
</mtable>
</mtd>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mn>1</mn>
<mi>n</mi>
</mrow>
</msub>
</mtd>
</mtr>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mn>21</mn>
</mrow>
</msub>
</mtd>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mn>22</mn>
</mrow>
</msub>
</mtd>
</mtr>
</mtable>
</mtd>
<mtd>
<mtable>
<mtr>
<mtd>
<mo></mo>
</mtd>
<mtd>
<mi></mi>
</mtd>
</mtr>
</mtable>
</mtd>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mn>2</mn>
<mi>n</mi>
</mrow>
</msub>
</mtd>
</mtr>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<mo></mo>
<mi></mi>
<mi></mi>
<mi></mi>
<mi></mi>
</mtd>
<mtd>
<mo></mo>
</mtd>
</mtr>
</mtable>
</mtd>
</mtr>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mi>m</mi>
<mn>1</mn>
</mrow>
</msub>
</mtd>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mi>m</mi>
<mn>2</mn>
</mrow>
</msub>
</mtd>
</mtr>
</mtable>
</mtd>
</mtr>
</mtable>
</mtd>
<mtd>
<mtable>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<mi></mi>
</mtd>
<mtd>
<mo></mo>
</mtd>
</mtr>
</mtable>
</mtd>
</mtr>
<mtr>
<mtd>
<mtable>
<mtr>
<mtd>
<mo></mo>
</mtd>
<mtd>
<mo></mo>
</mtd>
</mtr>
</mtable>
</mtd>
</mtr>
</mtable>
</mtd>
<mtd>
<mtable>
<mtr>
<mtd>
<mo></mo>
</mtd>
</mtr>
<mtr>
<mtd>
<msub>
<mrow>
<mi>a</mi>
</mrow>
<mrow>
<mi>m</mi>
<mi>n</mi>
</mrow>
</msub>
</mtd>
</mtr>
</mtable>
</mtd>
</mtr>
</mtable>
</mrow>
</mfenced>
<mi></mi>
</math>
`;
export const mfrac = `
<root>
<math>

View File

@ -41,37 +41,69 @@ class Vector {
}
class Matrix {
private readonly _open: string;
private readonly _close: string;
private readonly _separators: Separators;
private readonly _genericCommand = 'matrix';
constructor(open: string, close: string) {
this._separators = new Separators(open, close);
}
apply(latex: string): string {
const command = this._command;
const matrix = `\\begin{${command}}\n${latex}\n\\end{${command}}`;
return command === this._genericCommand ? this._separators.wrap(matrix) : matrix;
}
private get _command(): string {
if (this._separators.areParentheses()) return 'pmatrix';
if (this._separators.areSquareBrackets()) return 'bmatrix';
if (this._separators.areBrackets()) return 'Bmatrix';
if (this._separators.areDivides()) return 'vmatrix';
if (this._separators.areParallels()) return 'Vmatrix';
if (this._separators.areNotEqual()) return this._genericCommand;
return 'bmatrix';
}
}
class Separators {
readonly _open: string;
readonly _close: string;
constructor(open: string, close: string) {
this._open = open;
this._close = close;
}
apply(latex: string): string {
if (this._close || !this._open)
return `\\begin{${this._customCommand}}\n` + latex + `\n\\end{${this._customCommand}}`;
const matrix = `\\begin{${this._genericCommand}}\n` + latex + `\n\\end{${this._genericCommand}}`;
return new GenericWrapper(this._open, this._close).wrap(matrix);
wrap(str: string): string {
return new GenericWrapper(this._open, this._close).wrap(str);
}
private get _customCommand(): string {
switch (this._open) {
case '(':
return 'pmatrix';
case '|':
return 'vmatrix';
case '||':
return 'Vmatrix';
case '[':
return 'bmatrix';
case '{':
return 'Bmatrix';
default:
return this._genericCommand;
}
areParentheses(): boolean {
return this._compare('(', ')');
}
areSquareBrackets(): boolean {
return this._compare('[', ']');
}
areBrackets(): boolean {
return this._compare('{', '}');
}
areDivides(): boolean {
return this._compare('|', '|');
}
areParallels(): boolean {
return this._compare('||', '||');
}
areNotEqual(): boolean {
return this._open !== this._close;
}
private _compare(openToCompare: string, closeToCompare: string): boolean {
return this._open === openToCompare && this._close === closeToCompare;
}
}

View File

@ -3,9 +3,15 @@ import { MathMLTag } from './MathMLTag';
export class MTable extends MathMLTag {
constructor(value: string, attributes: Record<string, string>, children: MathMLTag[]) {
super('mtable', value, attributes, children);
this.addFlagRecursiveIfClassName(this.constructor.name, 'innerTable');
}
convert(): string {
return this._mapChildrenToLaTeX().join(' \\\\\n');
const tableContent = this._mapChildrenToLaTeX().join(' \\\\\n');
return this.hasFlag('innerTable') ? this._wrap(tableContent) : tableContent;
}
private _wrap(latex: string): string {
return `\\begin{matrix}${latex}\\end{matrix}`;
}
}

View File

@ -3,6 +3,7 @@ export class MathMLTag {
protected _value: string;
protected _attributes: Record<string, string>;
protected _children: MathMLTag[];
protected _flags: string[] = [];
constructor(name: string, value: string, attributes: Record<string, string>, children: MathMLTag[]) {
this._name = name;
@ -29,4 +30,19 @@ export class MathMLTag {
return firstChild.constructor.name === className || firstChild.isThere(className);
}
addFlag(flag: string): void {
if (!this._flags.includes(flag)) this._flags.push(flag);
}
addFlagRecursiveIfClassName(className: string, flag: string): void {
this._children.forEach((child) => {
if (child.constructor.name === className) child.addFlag(flag);
child.addFlagRecursiveIfClassName(className, flag);
});
}
hasFlag(flag: string): boolean {
return this._flags.includes(flag);
}
}