Skip to content

Commit 7772f04

Browse files
committed
Fix a number of line-breaking problems in tables and elsewhere. (mathjax/MathJax#3416)
1 parent efcdd46 commit 7772f04

File tree

6 files changed

+94
-53
lines changed

6 files changed

+94
-53
lines changed

ts/output/chtml/Wrappers/mrow.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,7 @@ export const ChtmlMrow = (function <N, T, D>(): ChtmlMrowClass<N, T, D> {
250250
);
251251
adaptor.setAttribute(parents[i], 'align', align);
252252
if (shift) {
253-
adaptor.setStyle(parents[i], 'position', 'relative');
254-
adaptor.setStyle(parents[i], 'left', this.em(shift));
253+
adaptor.setStyle(parents[i], 'margin-left', this.em(shift));
255254
}
256255
if (i < n && this.jax.math.display) {
257256
adaptor.setStyle(

ts/output/chtml/Wrappers/mtr.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ export const ChtmlMtr = (function <N, T, D>(): ChtmlMtrClass<N, T, D> {
164164
if (align !== 'baseline') {
165165
this.adaptor.setAttribute(this.dom[0], 'rowalign', align);
166166
}
167+
const { h, d } = this.getBBox();
168+
this.adaptor.setStyle(this.dom[0], 'height', this.em(h + d));
167169
}
168170
};
169171
})<any, any, any>();

ts/output/common/Wrapper.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ export class CommonWrapper<
457457
* @returns {number} The container width
458458
*/
459459
get containerWidth(): number {
460-
return this.jax.containerWidth;
460+
return this.parent ? this.parent.containerWidth : this.jax.containerWidth;
461461
}
462462

463463
/**

ts/output/common/Wrappers/mpadded.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ export function CommonMpaddedMixin<
171171
extends Base
172172
implements CommonMpadded<N, T, D, JX, WW, WF, WC, CC, VV, DD, FD, FC>
173173
{
174+
get containerWidth(): number {
175+
const attributes = this.node.attributes;
176+
const w = attributes.get('width') as string;
177+
if (!w.match(/^[-+]|%$/) && attributes.get('data-overflow') === 'linebreak') {
178+
return this.length2em(w);
179+
}
180+
return super.containerWidth;
181+
}
182+
174183
/**
175184
* @override
176185
*/

ts/output/common/Wrappers/mrow.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export function CommonMrowMixin<
327327
lines[n].R = this.bbox.R;
328328
} else {
329329
bbox.w = Math.max(...this.lineBBox.map((bbox) => bbox.w)); // natural width
330-
this.shiftLines(bbox.w);
330+
this.shiftLines(bbox);
331331
if (!this.jax.math.display && !this.linebreakOptions.inline) {
332332
bbox.pwidth = BBox.fullWidth;
333333
if (this.node.isInferred) {
@@ -391,11 +391,12 @@ export function CommonMrowMixin<
391391
}
392392

393393
/**
394-
* Handle alignment and shifting if lines
394+
* Handle alignment and shifting of lines
395395
*
396-
* @param {number} W The width of the container
396+
* @param {BBox} BBOX The bounding box of the container
397397
*/
398-
protected shiftLines(W: number) {
398+
protected shiftLines(BBOX: BBox) {
399+
const W = BBOX.w;
399400
const lines = this.lineBBox;
400401
const n = lines.length - 1;
401402
const [alignfirst, shiftfirst] = lines[1].indentData?.[0] || [
@@ -417,6 +418,10 @@ export function CommonMrowMixin<
417418
);
418419
bbox.L = 0;
419420
bbox.L = this.getAlignX(W, bbox, align) + shift;
421+
const w = bbox.L + bbox.w;
422+
if (w > BBOX.w) {
423+
BBOX.w = w;
424+
}
420425
}
421426
}
422427

@@ -432,7 +437,7 @@ export function CommonMrowMixin<
432437
if (recompute) return false;
433438
if (w !== null && this.bbox.w !== w) {
434439
this.bbox.w = w;
435-
this.shiftLines(w);
440+
this.shiftLines(this.bbox);
436441
}
437442
return true;
438443
}

ts/output/common/Wrappers/mtable.ts

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ export interface CommonMtable<
243243
* @param {number[]} D The maximum depth for each of the rows
244244
* @param {number[]} W The maximum width for each column
245245
* @param {number} M The current height for items aligned top and bottom
246-
* @returns {number} The updated value for M
247246
*/
248247
updateHDW(
249248
cell: WW,
@@ -254,17 +253,7 @@ export interface CommonMtable<
254253
D: number[],
255254
W: number[],
256255
M: number
257-
): number;
258-
259-
/**
260-
* Extend the H and D of a row to cover the maximum height needed by top/bottom aligned items
261-
*
262-
* @param {number} i The row whose hight and depth should be adjusted
263-
* @param {number[]} H The row heights
264-
* @param {number[]} D The row depths
265-
* @param {number} M The maximum height of top/bottom aligned items
266-
*/
267-
extendHD(i: number, H: number[], D: number[], M: number): void;
256+
): void;
268257

269258
/**
270259
* @param {WW} cell The cell to check for percentage widths
@@ -744,21 +733,29 @@ export function CommonMtableMixin<
744733
if (
745734
this.jax.math.root.attributes.get('overflow') !== 'linebreak' ||
746735
!this.jax.math.display
747-
)
736+
) {
748737
return;
749-
const { D } = this.getTableData();
738+
}
739+
const { H, D } = this.getTableData();
750740
let j = 0;
751741
let w = 0;
752742
for (const row of this.tableRows) {
753743
const cell = row.getChild(i);
754-
if (cell && cell.getBBox().w > W) {
755-
cell.childNodes[0].breakToWidth(W);
744+
if (cell) {
745+
const r = row.getBBox().rscale;
756746
const bbox = cell.getBBox();
757-
D[j] = Math.max(D[j], bbox.d);
758-
if (bbox.w > w) {
759-
w = bbox.w;
747+
if (cell && bbox.w * r > W) {
748+
cell.childNodes[0].breakToWidth(W);
749+
const align = row.node.attributes.get('rowalign') as string;
750+
this.updateHDW(cell, i, j, align, H, D);
751+
}
752+
if (bbox.w * r > w) {
753+
w = bbox.w * r;
760754
}
761755
}
756+
const bbox = row.getBBox();
757+
bbox.h = H[j];
758+
bbox.d = D[j];
762759
j++;
763760
}
764761
//
@@ -791,27 +788,72 @@ export function CommonMtableMixin<
791788
const LW = [0];
792789
const rows = this.tableRows;
793790
for (let j = 0; j < rows.length; j++) {
794-
let M = 0;
795791
const row = rows[j];
796792
const align = row.node.attributes.get('rowalign') as string;
797793
for (let i = 0; i < row.numCells; i++) {
798794
const cell = row.getChild(i);
799-
M = this.updateHDW(cell, i, j, align, H, D, W, M);
795+
this.updateHDW(cell, i, j, align, H, D, W);
800796
this.recordPWidthCell(cell, i);
801797
}
802798
NH[j] = H[j];
803799
ND[j] = D[j];
804800
if (row.labeled) {
805-
M = this.updateHDW(row.childNodes[0], 0, j, align, H, D, LW, M);
801+
this.updateHDW(row.childNodes[0], 0, j, align, H, D, LW);
806802
}
807-
this.extendHD(j, H, D, M);
808-
this.extendHD(j, NH, ND, M);
803+
row.bbox.h = H[j];
804+
row.bbox.d = D[j];
809805
}
810806
const L = LW[0];
811807
this.data = { H, D, W, NH, ND, L };
812808
return this.data;
813809
}
814810

811+
/**
812+
* Functions for adjusting the H and D values for cells
813+
* that are aligned by top, bottom, center, axis, and baseline.
814+
*/
815+
protected adjustHD: {
816+
[name: string]: (
817+
h: number,
818+
d: number,
819+
H: number[],
820+
D: number[],
821+
j: number
822+
) => void;
823+
} = {
824+
top: (h, d, H, D, j) => {
825+
if (h > H[j]) {
826+
D[j] -= h - H[j];
827+
H[j] = h;
828+
}
829+
if (h + d > H[j] + D[j]) {
830+
D[j] = h + d - H[j];
831+
}
832+
},
833+
bottom: (h, d, H, D, j) => {
834+
if (d > D[j]) {
835+
H[j] -= d - D[j];
836+
D[j] = d;
837+
}
838+
if (h + d > H[j] + D[j]) {
839+
H[j] = h + d - D[j];
840+
}
841+
},
842+
center: (h, d, H, D, j) => {
843+
if (h + d > H[j] + D[j]) {
844+
H[j] = D[j] = (h + d) / 2;
845+
}
846+
},
847+
other: (h, d, H, D, j) => {
848+
if (h > H[j]) {
849+
H[j] = h;
850+
}
851+
if (d > D[j]) {
852+
D[j] = d;
853+
}
854+
},
855+
};
856+
815857
/**
816858
* @override
817859
*/
@@ -822,9 +864,8 @@ export function CommonMtableMixin<
822864
align: string,
823865
H: number[],
824866
D: number[],
825-
W: number[],
826-
M: number
827-
): number {
867+
W: number[] = null
868+
) {
828869
let { h, d, w } = cell.getBBox();
829870
const scale = cell.parent.bbox.rscale;
830871
if (cell.parent.bbox.rscale !== 1) {
@@ -836,27 +877,12 @@ export function CommonMtableMixin<
836877
if (h < 0.75) h = 0.75;
837878
if (d < 0.25) d = 0.25;
838879
}
839-
let m = 0;
840880
align = (cell.node.attributes.get('rowalign') as string) || align;
841-
if (align !== 'baseline' && align !== 'axis') {
842-
m = h + d;
843-
h = d = 0;
881+
if (!Object.hasOwn(this.adjustHD, align)) {
882+
align = 'other';
844883
}
845-
if (h > H[j]) H[j] = h;
846-
if (d > D[j]) D[j] = d;
847-
if (m > M) M = m;
884+
this.adjustHD[align](h, d, H, D, j);
848885
if (W && w > W[i]) W[i] = w;
849-
return M;
850-
}
851-
852-
/**
853-
* @override
854-
*/
855-
public extendHD(i: number, H: number[], D: number[], M: number) {
856-
const d = (M - (H[i] + D[i])) / 2;
857-
if (d < 0.00001) return;
858-
H[i] += d;
859-
D[i] += d;
860886
}
861887

862888
/**

0 commit comments

Comments
 (0)