Skip to content

Commit dab5364

Browse files
committed
Use cell based table rendering
* Add hline search in matrix construction: ** This avoids a second scan later for the cost of some memory overhead * Parse | in array column specification * Add CSS based table lines as done by TMML, cf. w3c/mathml-core#245 Bug: T377167 Change-Id: I6e29b47b1731638ea9b06de3006ce2834e4f0c68
1 parent 7acc46e commit dab5364

File tree

6 files changed

+162
-59
lines changed

6 files changed

+162
-59
lines changed

modules/ext.math.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,20 @@ div.mwe-math-element {
6262
overflow-x: auto;
6363
max-width: 100%;
6464
}
65+
66+
/* Polyfill for MathML matrix elements with menclose https://github.com/w3c/mathml-core/issues/245 */
67+
mtd.mwe-math-matrix-top {
68+
border-top: 0.06em solid;
69+
}
70+
71+
mtd.mwe-math-matrix-bottom {
72+
border-bottom: 0.06em solid;
73+
}
74+
75+
mtd.mwe-math-matrix-left {
76+
border-left: 0.06em solid;
77+
}
78+
79+
mtd.mwe-math-matrix-right {
80+
border-right: 0.06em solid;
81+
}

src/WikiTexVC/MMLmappings/BaseParsing.php

Lines changed: 23 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -515,34 +515,18 @@ public static function matrix( Matrix $node, $passedArgs, $operatorContent,
515515
$vspacing = null, $style = null, $cases = null, $numbered = null ) {
516516
$resInner = '';
517517
$mtr = new MMLmtr();
518-
$mtd = new MMLmtd();
519-
$tableArgs = [ "columnspacing" => "1em", "rowspacing" => "4pt", 'rowlines' => '' ];
520-
$columnInfo = trim( $node->getColumnSpecs()->render(), "{} \n\r\t\v\x00" );
518+
$tableArgs = [ "columnspacing" => "1em", "rowspacing" => "4pt" ];
519+
$boarder = $node->getBoarder();
521520
if ( $align ) {
522521
$tableArgs['columnalign'] = $align;
523-
} elseif ( $columnInfo ) {
524-
$align = '';
525-
foreach ( str_split( $columnInfo ) as $chr ) {
526-
switch ( $chr ) {
527-
case 'r':
528-
$align .= 'right ';
529-
break;
530-
case 'l':
531-
$align .= 'left ';
532-
break;
533-
case 'c':
534-
$align .= 'center ';
535-
break;
536-
}
537-
}
538-
$tableArgs['columnalign'] = $align;
522+
} elseif ( $node->hasColumnInfo() ) {
523+
$tableArgs['columnalign'] = $node->getAlignInfo();
539524
}
540-
$mencloseArgs = [ 'notation' => '' ];
541-
542-
$lineNumber = 0;
525+
$rowNo = 0;
526+
$lines = $node->getLines();
543527
foreach ( $node as $row ) {
544528
$resInner .= $mtr->getStart();
545-
$solid = false;
529+
$colNo = 0;
546530
foreach ( $row as $cell ) {
547531
$usedArg = clone $cell;
548532
if ( $usedArg instanceof TexArray &&
@@ -551,42 +535,34 @@ public static function matrix( Matrix $node, $passedArgs, $operatorContent,
551535
$usedArg[0]->getArg() === '\\hline '
552536
) {
553537
$usedArg->pop();
554-
if ( $lineNumber === 0 ) {
555-
$mencloseArgs['notation'] .= 'top ';
556-
} elseif ( $lineNumber === $node->getLength() - 1 &&
538+
if ( $rowNo === $node->getLength() - 1 &&
557539
$usedArg->getLength() === 0
558540
) {
559-
$mencloseArgs['notation'] .= 'bottom ';
560541
// remove the started row
561542
$resInner = substr( $resInner, 0, -1 * strlen( $mtr->getStart() ) );
562543
continue 2;
563544
}
564-
$solid = true;
565545
}
546+
$mtdAttributes = [];
547+
$texclass = $lines[$rowNo] ? TexClass::TOP : '';
548+
$texclass .= $lines[$rowNo + 1] ?? false ? ' ' . TexClass::BOTTOM : '';
549+
$texclass .= $boarder[$colNo] ?? false ? ' ' . TexClass::LEFT : '';
550+
$texclass .= $boarder[$colNo + 1 ] ?? false ? ' ' . TexClass::RIGHT : '';
551+
$texclass = trim( $texclass );
552+
if ( $texclass ) {
553+
$mtdAttributes['class'] = $texclass;
554+
}
555+
$mtd = new MMLmtd( '', $mtdAttributes );
556+
566557
$resInner .= $mtd->encapsulateRaw( $usedArg->renderMML( $passedArgs, [ 'inMatrix'
567558
=> true ]
568559
) );
569-
}
570-
if ( $lineNumber > 0 ) {
571-
$tableArgs['rowlines'] .= $solid ? 'solid ' : 'none ';
560+
$colNo++;
572561
}
573562
$resInner .= $mtr->getEnd();
574-
$lineNumber++;
575-
}
576-
if ( !str_contains( $tableArgs['rowlines'], 'solid' ) ) {
577-
unset( $tableArgs['rowlines'] );
563+
$rowNo++;
578564
}
579565
$mrow = new MMLmrow();
580-
if ( $columnInfo ) {
581-
// TBD this is just simple check, create a parsing function for hlines when there are more cases
582-
if ( str_contains( $columnInfo, "|" ) ) {
583-
584-
$mencloseArgs['notation'] .= "left right";
585-
// it seems this is creted when left and right is solely coming from columninfo
586-
$tableArgs = array_merge( $tableArgs, [ "columnlines" => "solid" ] );
587-
}
588-
589-
}
590566
$mtable = new MMLmtable( "", $tableArgs );
591567
if ( $cases || ( $open != null && $close != null ) ) {
592568
$bm = new BaseMethods();
@@ -607,15 +583,9 @@ public static function matrix( Matrix $node, $passedArgs, $operatorContent,
607583
$mmlMoClose = $mmlMoClose->encapsulateRaw( $close );
608584
}
609585
$resInner = $mmlMoOpen . $mtable->encapsulateRaw( $resInner ) . $mmlMoClose;
610-
} else {
611-
$resInner = $mtable->encapsulateRaw( $resInner );
612-
}
613-
if ( $mencloseArgs['notation'] ) {
614-
$menclose = new MMLmenclose( "", $mencloseArgs );
615-
return $mrow->encapsulateRaw( $menclose->encapsulateRaw( $resInner ) );
616-
586+
return $mrow->encapsulateRaw( $resInner );
617587
}
618-
return $mrow->encapsulateRaw( $resInner );
588+
return $mtable->encapsulateRaw( $resInner );
619589
}
620590

621591
public static function namedOp( $node, $passedArgs, $operatorContent, $name, $id = null ) {

src/WikiTexVC/MMLmappings/TexConstants/TexClass.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,8 @@ class TexClass {
1313
public const INNER = "INNER";
1414
public const VCENTER = "VCENTER";
1515
public const NONE = "-1";
16+
public const TOP = "mwe-math-matrix-top";
17+
public const BOTTOM = "mwe-math-matrix-bottom";
18+
public const LEFT = "mwe-math-matrix-left";
19+
public const RIGHT = "mwe-math-matrix-right";
1620
}

src/WikiTexVC/Nodes/Matrix.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@ class Matrix extends TexArray {
1111

1212
/** @var string */
1313
private $top;
14+
private array $lines = [];
1415

1516
private ?TexArray $columnSpecs = null;
1617

18+
private ?string $renderedColumSpecs = null;
19+
private ?array $boarder = null;
20+
21+
private ?string $alignInfo = null;
22+
1723
/**
1824
* @param string $top
1925
* @param TexArray $mainarg
@@ -24,6 +30,7 @@ public function __construct( string $top, TexArray $mainarg ) {
2430
if ( !$row instanceof TexArray ) {
2531
throw new InvalidArgumentException( 'Nested arguments have to be type of TexArray' );
2632
}
33+
$this->lines[] = $row->containsFunc( '\hline' );
2734
}
2835
if ( $mainarg instanceof Matrix ) {
2936
$this->args = $mainarg->args;
@@ -34,6 +41,10 @@ public function __construct( string $top, TexArray $mainarg ) {
3441
$this->top = $top;
3542
}
3643

44+
public function getLines(): array {
45+
return $this->lines;
46+
}
47+
3748
/**
3849
* @return string
3950
*/
@@ -46,15 +57,32 @@ public function setTop( string $top ): Matrix {
4657
return $this;
4758
}
4859

49-
public function getColumnSpecs(): TexArray {
50-
return $this->columnSpecs ?? new TexArray();
60+
public function getRenderedColumnSpecs(): string {
61+
if ( $this->renderedColumSpecs == null ) {
62+
$this->renderColumnSpecs();
63+
}
64+
return $this->renderedColumSpecs;
5165
}
5266

5367
public function setColumnSpecs( TexArray $specs ): Matrix {
5468
$this->columnSpecs = $specs;
69+
$this->renderedColumSpecs = null;
70+
$this->alignInfo = null;
71+
$this->boarder = null;
5572
return $this;
5673
}
5774

75+
public function hasColumnInfo(): bool {
76+
return $this->getRenderedColumnSpecs() !== '';
77+
}
78+
79+
public function getAlignInfo(): string {
80+
if ( $this->alignInfo == null ) {
81+
$this->renderColumnSpecs();
82+
}
83+
return $this->alignInfo;
84+
}
85+
5886
/**
5987
* @return TexArray
6088
*/
@@ -139,4 +167,42 @@ public function getIterator(): Generator {
139167
return parent::getIterator();
140168
}
141169

170+
/**
171+
* @return void
172+
*/
173+
public function renderColumnSpecs(): void {
174+
$colSpecs = $this->columnSpecs ?? new TexArray();
175+
$this->renderedColumSpecs = trim( $colSpecs->render(), "{} \n\r\t\v\x00" );
176+
$align = '';
177+
$colNo = 0;
178+
$this->boarder = [];
179+
foreach ( str_split( $this->renderedColumSpecs ) as $chr ) {
180+
switch ( $chr ) {
181+
case '|':
182+
$this->boarder[$colNo] = true;
183+
break;
184+
case 'r':
185+
$align .= 'right ';
186+
$colNo++;
187+
break;
188+
case 'l':
189+
$align .= 'left ';
190+
$colNo++;
191+
break;
192+
case 'c':
193+
$colNo++;
194+
$align .= 'center ';
195+
break;
196+
}
197+
}
198+
$this->alignInfo = $align;
199+
}
200+
201+
public function getBoarder(): array {
202+
if ( $this->boarder == null ) {
203+
$this->renderColumnSpecs();
204+
}
205+
return $this->boarder;
206+
}
207+
142208
}

tests/phpunit/unit/WikiTexVC/MMLmappings/BaseParsingTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public function testHLineLastLine() {
149149
new TexArray( new TexArray( new Literal( '\\hline ' ), new Literal( 'a'
150150
) ) ) ) );
151151
$result = BaseParsing::matrix( $matrix, [], null, 'matrix', '002A' );
152-
$this->assertStringContainsString( 'solid', $result );
152+
$this->assertStringContainsString( 'class="mwe-math-matrix-top"', $result );
153153
$this->assertStringContainsString( '<mi>a</mi>', $result );
154154
}
155155

@@ -161,8 +161,8 @@ public function testComplicatedHline() {
161161
\\hline
162162
\\end{array}' )[0];
163163
$result = BaseParsing::matrix( $matrix, [], null, 'matrix', '002A' );
164-
$this->assertStringContainsString( 'solid none', $result );
165-
$this->assertStringContainsString( 'top bottom', $result );
164+
$this->assertStringContainsString( 'class="mwe-math-matrix-top"', $result );
165+
$this->assertStringContainsString( 'class="mwe-math-matrix-top mwe-math-matrix-bottom"', $result );
166166
}
167167

168168
public function testHandleOperatorName() {

tests/phpunit/unit/WikiTexVC/Nodes/MatrixTest.php

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,52 @@ public function testTop() {
9999

100100
public function testColSpec() {
101101
$this->sampleMatrix->setColumnSpecs( TexArray::newCurly( new Literal( '2' ) ) );
102-
$this->assertEquals( '{2}', $this->sampleMatrix->getColumnSpecs()->render() );
102+
$this->assertSame( '2', $this->sampleMatrix->getRenderedColumnSpecs() );
103+
}
104+
105+
public function testAdvColSpec() {
106+
$this->sampleMatrix->setColumnSpecs( TexArray::newCurly( new Literal( '{r|l}' ) ) );
107+
$this->assertSame( 'r|l', $this->sampleMatrix->getRenderedColumnSpecs() );
108+
$this->assertEquals( 'right left ', $this->sampleMatrix->getAlignInfo() );
109+
$this->assertEquals( [ 1 => true ], $this->sampleMatrix->getBoarder() );
110+
}
111+
112+
public function testGetLines() {
113+
$real = $this->sampleMatrix->getLines();
114+
$this->assertNotEmpty( $real );
115+
$this->assertFalse( $real[0] );
116+
}
117+
118+
public function testLinesBottom() {
119+
$matrix = new Matrix( 'matrix',
120+
new TexArray( new TexArray( new Literal( 'a' ) ),
121+
new TexArray( new TexArray( new Literal( '\\hline ' ) ) ) ) );
122+
$real = $matrix->getLines();
123+
$this->assertNotEmpty( $real );
124+
$this->assertFalse( $real[0] );
125+
$this->assertTrue( $real[1] );
126+
$this->assertCount( 2, $real );
127+
}
128+
129+
public function testLinesTop() {
130+
$matrix = new Matrix( 'matrix',
131+
new TexArray( new TexArray( new TexArray( new Literal( '\\hline ' ), new Literal( 'a'
132+
) ) ) ) );
133+
$real = $matrix->getLines();
134+
$this->assertNotEmpty( $real );
135+
$this->assertTrue( $real[0] );
136+
$this->assertCount( 1, $real );
137+
}
138+
139+
public function testLinesLast() {
140+
$matrix = new Matrix( 'matrix',
141+
new TexArray( new TexArray( new Literal( 'a' ) ),
142+
new TexArray( new TexArray( new Literal( '\\hline ' ), new Literal( 'a'
143+
) ) ) ) );
144+
$real = $matrix->getLines();
145+
$this->assertNotEmpty( $real );
146+
$this->assertFalse( $real[0] );
147+
$this->assertTrue( $real[1] );
148+
$this->assertCount( 2, $real );
103149
}
104150
}

0 commit comments

Comments
 (0)