Skip to content

Commit 802b95c

Browse files
committed
Improve detection of separator row.
Related #1
1 parent 03ff15b commit 802b95c

4 files changed

Lines changed: 88 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes to the `markdowntableprettify` extension will be documented
44
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased]
7+
- Fixed issue #1 by improving the detection of header separator to avoid unintended table formatting failures.
78

89
## 1.0.0 - 2017-04-03
910
### Added

demonstration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ int|32|Integer|
1616

1717
Create missing ending table border if the beginning already has a border:
1818
|Primitive Type|Size(bit)|Wrapper
19-
|-|-|-|
19+
|-|-|-
2020
|short|16|Short
2121
|int|32|Integer
2222

src/tableFactory.ts

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,59 @@ export class TableFactory implements ITableFactory {
1414
.map(l => l.split("|"))
1515
.filter(arr => !(arr.length == 1 && arr[0] == ""));
1616

17+
if (!TableValidator.rowAndColumnSizeValid(rows))
18+
return null;
19+
1720
// remove the separator line from second line
18-
const rowsWithoutSeparator = TableValidator.containsHeaderSeparator(rows)
21+
const rowsWithoutSeparator = TableValidator.hasValidSeparators(rows)
1922
? rows.filter((v, i) => i != 1) // remove the separator line from second line
2023
: null;
2124

22-
if (!TableValidator.areValidRows(rowsWithoutSeparator))
23-
return null;
24-
25-
return new Table(rowsWithoutSeparator);
25+
return rowsWithoutSeparator != null ? new Table(rowsWithoutSeparator) : null;
2626
}
2727
}
2828

2929
class TableValidator {
30-
public static containsHeaderSeparator(rawRows: string[][]): boolean {
30+
public static rowAndColumnSizeValid(rawRows: string[][]): boolean {
31+
return !!rawRows &&
32+
rawRows.length > 2 && // at least two rows are required besides the separator
33+
rawRows[0].length > 1 && // at least two columns are required
34+
rawRows.every(r => r.length == rawRows[0].length); // all rows of a column must match the length of the first row of that column
35+
}
36+
37+
public static hasValidSeparators(rawRows: string[][]): boolean {
3138
if (!rawRows || rawRows.length < 1 || !rawRows[1])
3239
return false;
40+
41+
// if all columns are dashes, then it is valid
3342
const secondRow = rawRows[1];
34-
return secondRow.every((v, i) => this.isSeparator(v, i == 0 || i == secondRow.length - 1));
43+
const allCellsDash = secondRow.every(cell => this.composedOfDashes(cell));
44+
if (allCellsDash)
45+
return true;
46+
47+
// now it can only be valid of the table starts or ends with a border and the middle columns are dashes
48+
return this.allDashesWithBorder(secondRow);
3549
}
3650

37-
private static isSeparator(cellValue: string, isFirstOrLast: boolean): boolean {
38-
if (cellValue.trim() == "-")
39-
return true;
40-
// If the first or last column is empty then it still can be a header containing separator,
41-
// for example table starting or ending with borders ("|") would produce this.
42-
if (cellValue.trim() == "" && isFirstOrLast)
51+
private static composedOfDashes(cellValue: string): boolean {
52+
const trimmedSpace = cellValue.trim();
53+
const firstDash = trimmedSpace.replace(/(?!^)-/g, "");
54+
if (firstDash === "-")
4355
return true;
4456
return false;
4557
}
4658

47-
public static areValidRows(rawRows: string[][]): boolean {
48-
return !!rawRows &&
49-
rawRows.length > 1 && // at least two rows are required
50-
rawRows[0].length > 1 && // at least two columns are required
51-
rawRows.every(r => r.length == rawRows[0].length); // all rows of a column must match the length of the first row of that column
59+
private static allDashesWithBorder(secondRow: string[]): boolean {
60+
const hasStartingBorder = secondRow.length >= 3 && secondRow[0].trim() === "";
61+
const hasEndingBorder = secondRow.length >= 3 && secondRow[secondRow.length - 1].trim() === "";
62+
63+
let startIndex = hasStartingBorder ? 1 : 0;
64+
let endIndex = hasEndingBorder ? secondRow.length - 2 : secondRow.length - 1;
65+
66+
const middleColumns = secondRow.filter((v, i) => i >= startIndex && i <= endIndex);
67+
const middleColumnsAllDash = middleColumns.every(cell => this.composedOfDashes(cell));
68+
if (middleColumnsAllDash && (hasStartingBorder || hasEndingBorder))
69+
return true;
70+
return false;
5271
}
5372
}

test/tableFactory.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,53 @@ suite("TableFactory tests", () => {
6767
assert.equal(true, table != null);
6868
assert.equal(true, (table as ITable) != null);
6969
});
70+
71+
test("create() two column header with longer separator and a row table instance created", () => {
72+
const text = `header 1 | header 2
73+
----|----
74+
value 1 | value 2`;
75+
const factory = new TableFactory();
76+
const table = factory.create(text);
77+
assert.equal(true, table != null);
78+
assert.equal(true, (table as ITable) != null);
79+
});
80+
81+
test("create() table with left border and valid separator a table instance created", () => {
82+
const text = `|header 1 | header 2
83+
|-|----
84+
|value 1 | value 2`;
85+
const factory = new TableFactory();
86+
const table = factory.create(text);
87+
assert.equal(true, table != null);
88+
assert.equal(true, (table as ITable) != null);
89+
});
90+
91+
test("create() table with right border and valid separator a table instance created", () => {
92+
const text = `header 1 | header 2|
93+
---|----|
94+
value 1 | value 2|`;
95+
const factory = new TableFactory();
96+
const table = factory.create(text);
97+
assert.equal(true, table != null);
98+
assert.equal(true, (table as ITable) != null);
99+
});
100+
101+
test("create() table with both borders and valid separator a table instance created", () => {
102+
const text = `|header 1 | header 2|
103+
|---|---|
104+
|value 1 | value 2|`;
105+
const factory = new TableFactory();
106+
const table = factory.create(text);
107+
assert.equal(true, table != null);
108+
assert.equal(true, (table as ITable) != null);
109+
});
110+
111+
test("create() two column header with invalid separator null table returned", () => {
112+
const text = `header 1 | header 2
113+
|
114+
value 1 | value 2`;
115+
const factory = new TableFactory();
116+
const table = factory.create(text);
117+
assert.equal(table, null);
118+
});
70119
});

0 commit comments

Comments
 (0)