Skip to content

Commit 55da586

Browse files
committed
Improve handling of table edge cases
1 parent e9d05d8 commit 55da586

3 files changed

Lines changed: 44 additions & 7 deletions

File tree

lib/src/org/model/org_table.dart

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,35 @@ class OrgTable extends OrgParentNode with OrgElement {
4040
.whereType<OrgTableCellRow>()
4141
.map((row) => row.cellCount)
4242
.toSet()
43-
.length <
44-
2;
43+
.length ==
44+
1;
4545

4646
/// The maximum number of columns in any row of the table
47-
int get columnCount =>
48-
rows.whereType<OrgTableCellRow>().map((row) => row.cellCount).reduce(max);
47+
int get columnCount {
48+
final cellRows = rows
49+
.whereType<OrgTableCellRow>()
50+
.map((row) => row.cellCount)
51+
.toList(growable: false);
52+
return cellRows.isEmpty ? 0 : cellRows.reduce(max);
53+
}
4954

5055
/// Determine whether the column number [colIdx] should be treated as a
5156
/// numeric column. A certain percentage of non-numeric cells are tolerated.
57+
///
58+
/// This value is not meaningful if [colIdx] is out of range for the table.
5259
bool columnIsNumeric(int colIdx) {
5360
final cells = rows
5461
.whereType<OrgTableCellRow>()
55-
.map((row) => row.cells[colIdx])
62+
.map((row) => colIdx >= row.cells.length ? null : row.cells[colIdx])
5663
.toList(growable: false);
64+
if (cells.every((c) => c == null)) {
65+
throw RangeError.range(
66+
colIdx, 0, columnCount, 'No such column in any row', null);
67+
}
5768
final totalCount = cells.length;
58-
final emptyCount = cells.where((c) => c.isEmpty).length;
69+
final emptyCount = cells.where((c) => c == null || c.isEmpty).length;
5970
final nonEmptyCount = totalCount - emptyCount;
60-
final numberCount = cells.where((c) => c.isNumeric).length;
71+
final numberCount = cells.where((c) => c?.isNumeric == true).length;
6172
return numberCount / nonEmptyCount >= _orgTableNumberFraction;
6273
}
6374

@@ -203,6 +214,7 @@ class OrgTableCell extends OrgParentNode {
203214
copyWith(content: children.single as OrgContent);
204215

205216
bool get isEmpty => content.children.isEmpty;
217+
bool get isNotEmpty => !isEmpty;
206218

207219
bool get isNumeric => _isNumeric(content);
208220

test/org/model/table_test.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ void main() {
3838
expect(table.columnCount, 1);
3939
expect(table.columnIsNumeric(0), isFalse);
4040
expect(() => table.columnIsNumeric(1), throwsRangeError);
41+
expect(() => table.columnIsNumeric(-1), throwsRangeError);
4142
});
4243
});
4344
}

test/org/parser/table_test.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ void main() {
3131
final table = result.value as OrgTable;
3232
final row0 = table.rows[0] as OrgTableCellRow;
3333
expect(row0.cells[0].content.children.isEmpty, isTrue);
34+
expect(table.rectangular, isTrue);
35+
expect(table.columnCount, 1);
36+
expect(table.columnIsNumeric(0), isFalse);
3437
});
3538
test('With non-markup plus in cell', () {
3639
// https://github.com/amake/orgro/issues/175
@@ -42,6 +45,7 @@ void main() {
4245
''');
4346
final table = result.value as OrgTable;
4447
expect(table.columnCount, 2);
48+
expect(table.rectangular, isTrue);
4549
expect(table.rows[0], isA<OrgTableDividerRow>());
4650
final row1 = table.rows[1] as OrgTableCellRow;
4751
final cell0 = row1.cells[0].content.children[0] as OrgPlainText;
@@ -54,5 +58,25 @@ void main() {
5458
expect(cell0Row4.leadingDecoration, '+');
5559
expect(cell0Row4.trailingDecoration, '+');
5660
});
61+
test('no columns', () {
62+
final result = parser.parse('+-+');
63+
final table = result.value as OrgTable;
64+
expect(table.rows[0], isA<OrgTableDividerRow>());
65+
expect(table.columnCount, 0);
66+
expect(table.rectangular, isFalse);
67+
expect(() => table.columnIsNumeric(0), throwsRangeError);
68+
});
69+
test('uneven rows', () {
70+
final result = parser.parse('''| a | b | c |
71+
|---+---+---|
72+
| 1 | 2 |
73+
| 3 | 4 | 5 |
74+
''');
75+
final table = result.value as OrgTable;
76+
expect(table.columnCount, 3);
77+
expect(table.rectangular, isFalse);
78+
expect(table.columnIsNumeric(2), isTrue);
79+
expect(table.rows.length, 4);
80+
});
5781
});
5882
}

0 commit comments

Comments
 (0)