Skip to content

Commit

Permalink
fix: fixed arnog#2291. Regression. Atom lists are immutable.
Browse files Browse the repository at this point in the history
  • Loading branch information
arnog committed Feb 8, 2024
1 parent 24081c2 commit 2553750
Show file tree
Hide file tree
Showing 40 changed files with 705 additions and 690 deletions.
97 changes: 50 additions & 47 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/atoms/accent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class AccentAtom extends Atom {
options: CreateAtomOptions & {
accentChar?: number;
svgAccent?: string;
body: null | Atom[];
body: null | readonly Atom[];
}
) {
super({ ...options, type: 'accent', body: options.body ?? undefined });
Expand Down
64 changes: 36 additions & 28 deletions src/atoms/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type ColumnFormat =
}
| {
// The width of a gap between columns, or a LaTeX expression between columns
gap?: number | Atom[];
gap?: number | readonly Atom[];
}
| {
// A rule (line) separating columns
Expand Down Expand Up @@ -98,9 +98,9 @@ type ArrayRow = {

function normalizeArray(
atom: ArrayAtom,
array: Atom[][][],
colFormat: ColumnFormat[]
): Atom[][][] {
array: (readonly Atom[])[][],
colFormat: readonly ColumnFormat[]
): (readonly Atom[])[][] {
//
// 1/
// - Fold the array so that there are no more columns of content than
Expand All @@ -115,13 +115,13 @@ function normalizeArray(

// Actual number of columns (at most `maxColCount`)
let colCount = 0;
const rows: Atom[][][] = [];
const rows: (readonly Atom[])[][] = [];

for (const row of array) {
let colIndex = 0;
colCount = Math.max(colCount, Math.min(row.length, maxColCount));
while (colIndex < row.length) {
const newRow: Atom[][] = [];
const newRow: (readonly Atom[])[] = [];
const lastCol = Math.min(row.length, colIndex + maxColCount);
while (colIndex < lastCol) {
const cell = row[colIndex];
Expand Down Expand Up @@ -156,7 +156,7 @@ function normalizeArray(
//
// 3/ Fill out any missing cells
//
const result: Atom[][][] = [];
const result: (readonly Atom[])[][] = [];
for (const row of rows) {
if (row.length !== colCount) {
for (let i = row.length; i < colCount; i++) {
Expand Down Expand Up @@ -193,10 +193,10 @@ function normalizeArray(

// See http://ctan.math.utah.edu/ctan/tex-archive/macros/latex/base/lttab.dtx
export class ArrayAtom extends Atom {
array: (undefined | Atom[])[][];
array: (undefined | readonly Atom[])[][];
environmentName: Environment;
rowGaps: Dimension[];
colFormat: ColumnFormat[];
rowGaps: readonly Dimension[];
colFormat: readonly ColumnFormat[];
arraystretch?: number;
arraycolsep?: number;
colSeparationType?: ColSeparationType;
Expand All @@ -207,8 +207,8 @@ export class ArrayAtom extends Atom {

constructor(
envName: Environment,
array: Atom[][][],
rowGaps: Dimension[],
array: (readonly Atom[])[][],
rowGaps: readonly Dimension[],
options: ArrayAtomConstructorOptions = {}
) {
super({ type: 'array' });
Expand Down Expand Up @@ -280,15 +280,15 @@ export class ArrayAtom extends Atom {
return result;
}

branch(cell: Branch): Atom[] | undefined {
branch(cell: Branch): readonly Atom[] | undefined {
if (!isCellBranch(cell)) return undefined;
return this.array[cell[0]][cell[1]] ?? undefined;
}

createBranch(cell: Branch): Atom[] {
if (!isCellBranch(cell)) return [];
this.isDirty = true;
return this.branch(cell) ?? [];
return (this.branch(cell) as Atom[]) ?? [];
}

get rowCount(): number {
Expand All @@ -303,18 +303,19 @@ export class ArrayAtom extends Atom {
return this.colFormat.filter((col) => Boolean(col['align'])).length;
}

removeBranch(name: Branch): Atom[] {
removeBranch(name: Branch): readonly Atom[] {
if (isNamedBranch(name)) return super.removeBranch(name);

const children = this.branch(name)!;
const [_first, ...children] = this.branch(name)!;
// Drop the 'first' element
console.assert(_first.type === 'first');

this.array[name[0]][name[1]] = undefined;
children.forEach((x) => {
x.parent = undefined;
x.parentBranch = undefined;
});
// Drop the 'first' element
console.assert(children[0].type === 'first');
children.shift();

this.isDirty = true;
return children;
}
Expand All @@ -323,7 +324,7 @@ export class ArrayAtom extends Atom {
return this.children.length > 0;
}

get children(): Atom[] {
get children(): readonly Atom[] {
const result: Atom[] = [];
for (const row of this.array) {
for (const cell of row) {
Expand Down Expand Up @@ -635,11 +636,18 @@ export class ArrayAtom extends Atom {
return joinLatex(result);
}

getCell(row: number, col: number): Atom[] | undefined {
forEachCell(
callback: (cell: readonly Atom[], row: number, col: number) => void
): void {
for (let i = 0; i < this.rowCount; i++)
for (let j = 0; j < this.colCount; j++) callback(this.array[i][j]!, i, j);
}

getCell(row: number, col: number): readonly Atom[] | undefined {
return this.array[row][col];
}

setCell(row: number, column: number, value: Atom[]): void {
setCell(row: number, column: number, value: readonly Atom[]): void {
console.assert(
this.type === 'array' &&
Array.isArray(this.array) &&
Expand All @@ -664,7 +672,7 @@ export class ArrayAtom extends Atom {

addRowBefore(row: number): void {
console.assert(this.type === 'array' && Array.isArray(this.array));
const newRow: Atom[][] = [];
const newRow: (readonly Atom[])[] = [];
for (let i = 0; i < this.colCount; i++)
newRow.push(makePlaceholderCell(this));

Expand All @@ -680,7 +688,7 @@ export class ArrayAtom extends Atom {

addRowAfter(row: number): void {
console.assert(this.type === 'array' && Array.isArray(this.array));
const newRow: Atom[][] = [];
const newRow: (readonly Atom[])[] = [];
for (let i = 0; i < this.colCount; i++)
newRow.push(makePlaceholderCell(this));

Expand Down Expand Up @@ -774,8 +782,8 @@ export class ArrayAtom extends Atom {
this.isDirty = true;
}

get cells(): Atom[][] {
const result: Atom[][] = [];
get cells(): (readonly Atom[])[] {
const result: (readonly Atom[])[] = [];
for (const row of this.array) {
for (const cell of row)
if (cell) result.push(cell.filter((x) => x.type !== 'first'));
Expand All @@ -787,7 +795,7 @@ export class ArrayAtom extends Atom {
/**
* Create a matrix cell with a placeholder atom in it.
*/
function makePlaceholderCell(parent: ArrayAtom): Atom[] {
function makePlaceholderCell(parent: ArrayAtom): readonly Atom[] {
const first = new Atom({ type: 'first', mode: parent.mode });
first.parent = parent;
const placeholder = new PlaceholderAtom();
Expand All @@ -811,7 +819,7 @@ function makeColOfRepeatingElements(
context: Context,
rows: ArrayRow[],
offset: number,
element: Atom[] | undefined
element: readonly Atom[] | undefined
): Box | null {
if (!element) return null;
const col: VBoxElementAndShift[] = [];
Expand Down
2 changes: 1 addition & 1 deletion src/atoms/box.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class BoxAtom extends Atom {

constructor(
options: CreateAtomOptions & {
body: Atom[];
body: readonly Atom[];
framecolor?: LatexValue;
backgroundcolor?: LatexValue;
padding?: LatexValue;
Expand Down
Loading

0 comments on commit 2553750

Please sign in to comment.