Skip to content

Commit bf625ff

Browse files
committed
Add support for equalcolumns and use service routines SUM() and isPercent() for common actions.
1 parent 49ea3d0 commit bf625ff

File tree

1 file changed

+53
-12
lines changed

1 file changed

+53
-12
lines changed

mathjax3-ts/output/chtml/Wrappers/mtable.ts

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,27 @@ export type TableData = {
4040
W: number[];
4141
};
4242

43+
/*
44+
* Sum the elements of an array
45+
*/
46+
function SUM(A: number[]) {
47+
return A.reduce((a, b) => a + b, 0);
48+
}
49+
50+
/*
51+
* Get the maximum value from an array
52+
*/
53+
function MAX(A: number[]) {
54+
return A.reduce((a, b) => Math.max(a, b), 0);
55+
}
56+
57+
/*
58+
* Test if a value is a percentage
59+
*/
60+
function isPercent(x: string) {
61+
return x.match(/%\s*$/);
62+
}
63+
4364
/*****************************************************************/
4465
/*
4566
* The CHTMLmtable wrapper for the MmlMtable object
@@ -99,8 +120,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
99120
//
100121
// Determine the number of columns and rows
101122
//
102-
this.numCols = this.childNodes.map(row => (row as CHTMLmtr<N, T, D>).numCells)
103-
.reduce((a, b) => Math.max(a, b), 0);
123+
this.numCols = MAX(this.childNodes.map(row => (row as CHTMLmtr<N, T, D>).numCells));
104124
this.numRows = this.childNodes.length;
105125
//
106126
// Get the frame, row, and column parameters
@@ -243,10 +263,9 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
243263
//
244264
if (this.node.attributes.get('equalrows')) {
245265
const HD = this.getEqualRowHeight();
246-
height = [].concat(this.rLines, this.rSpace).reduce((a, b) => a + b, 0)
247-
+ HD * this.numRows;
266+
height = SUM([].concat(this.rLines, this.rSpace)) + HD * this.numRows;
248267
} else {
249-
height = H.concat(D, this.rLines, this.rSpace).reduce((a, b) => a + b, 0);
268+
height = SUM(H.concat(D, this.rLines, this.rSpace));
250269
}
251270
height += (this.frame ? .14 + 2 * this.fSpace[1] : 0);
252271
//
@@ -258,8 +277,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
258277
//
259278
// Get the expected width of the table
260279
//
261-
width = CW.concat(this.cLines, this.cSpace).reduce((a, b) => a + b, 0)
262-
+ (this.frame ? .14 + 2 * this.fSpace[0] : 0);
280+
width = SUM(CW.concat(this.cLines, this.cSpace)) + (this.frame ? .14 + 2 * this.fSpace[0] : 0);
263281
//
264282
// If the table width is not 'auto', determine the specified width
265283
// and pick the larger of the specified and computed widths.
@@ -486,7 +504,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
486504
protected handleWidth() {
487505
let w = this.node.attributes.get('width') as string;
488506
if (w === 'auto') return;
489-
if (w.match(/%$/)) {
507+
if (isPercent(w)) {
490508
this.bbox.pwidth = w;
491509
} else {
492510
w = this.em(this.length2em(w) + (this.frame ? .14 : 0));
@@ -518,16 +536,39 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
518536
*/
519537
protected getColumnWidths() {
520538
const width = this.node.attributes.get('width') as string;
539+
if (this.node.attributes.get('equalcolumns')) {
540+
return this.getEqualColumns(width);
541+
}
521542
const swidths = this.getColumnAttributes('columnwidth', 0);
522543
if (width === 'auto') {
523544
return this.getColumnWidthsAuto(swidths);
524545
}
525-
if (width.match(/%$/)) {
546+
if (isPercent(width)) {
526547
return this.getColumnWidthsPercent(swidths, width);
527548
}
528549
return this.getColumnWidthsFixed(swidths, this.length2em(width));
529550
}
530551

552+
/*
553+
* For tables with equal columns, get the proper amount per row.
554+
*
555+
* @return{(string|number|null)[]} The array of widths
556+
*/
557+
protected getEqualColumns(width: string) {
558+
const n = Math.max(1, this.numCols);
559+
let cwidth;
560+
if (width === 'auto') {
561+
const {W} = this.getTableData();
562+
cwidth = MAX(W);
563+
} else if (isPercent(width)) {
564+
cwidth = this.percent(1 / n);
565+
} else {
566+
const w = SUM([].concat(this.cLines, this.cSpace)) + 2 * this.fSpace[0];
567+
cwidth = Math.max(0, this.length2em(width) - w) / n;
568+
}
569+
return Array(this.numCols).fill(cwidth);
570+
}
571+
531572
/*
532573
* For tables with width="auto", auto and fit columns
533574
* will end up being natural width, so don't need to
@@ -538,7 +579,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
538579
protected getColumnWidthsAuto(swidths: string[]) {
539580
return swidths.map(x => {
540581
if (x === 'auto' || x === 'fit') return null;
541-
if (x.match(/%$/)) return x;
582+
if (isPercent(x)) return x;
542583
return this.length2em(x);
543584
});
544585
}
@@ -558,7 +599,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
558599
const x = swidths[i];
559600
if (x === 'fit') return null;
560601
if (x === 'auto') return (hasFit ? W[i] : null);
561-
if (x.match(/%$/)) return x;
602+
if (isPercent(x)) return x;
562603
return this.length2em(x);
563604
});
564605
}
@@ -583,7 +624,7 @@ export class CHTMLmtable<N, T, D> extends CHTMLWrapper<N, T, D> {
583624
// separation and lines have been removed (cwidth), and
584625
// after the width of the columns have been removed (dw).
585626
//
586-
const cwidth = width - [].concat(this.cLines, this.cSpace).reduce((a, b) => a + b, 0) - 2 * this.fSpace[0];
627+
const cwidth = width - SUM([].concat(this.cLines, this.cSpace)) - 2 * this.fSpace[0];
587628
let dw = cwidth;
588629
indices.forEach(i => {
589630
const x = swidths[i];

0 commit comments

Comments
 (0)