Skip to content

Commit 28c4784

Browse files
authored
Merge pull request #48 from darkriszty/feature/indentation
Feature/indentation
2 parents 01e2f99 + 43456e8 commit 28c4784

25 files changed

Lines changed: 361 additions & 106 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
66

77
## [Unreleased]
88

9+
## 3.2.0 - 2020-12-14
10+
### Added
11+
- Issue #47: Support for indented tables.
12+
913
## 3.1.0 - 2020-11-04
1014
### Fixed
1115
- Issue #42: Don't alter selection for invalid range formatting attempt (does not impact CLI).

cli/cliPrettify.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ContentPadCalculator } from "../src/padCalculation/contentPadCalculator
1515
import { PadCalculatorSelector } from "../src/padCalculation/padCalculatorSelector";
1616
import { AlignmentMarkerStrategy } from "../src/viewModelFactories/alignmentMarking";
1717
import { TableStringWriter } from "../src/writers/tableStringWriter";
18+
import { FairTableIndentationDetector } from "../src/modelFactory/tableIndentationDetector";
1819

1920
export class CliPrettify {
2021

@@ -37,7 +38,8 @@ export class CliPrettify {
3738
new TableFactory(
3839
new AlignmentFactory(),
3940
new SelectionInterpreter(false),
40-
new TrimmerTransformer(new BorderTransformer(null))
41+
new TrimmerTransformer(new BorderTransformer(null)),
42+
new FairTableIndentationDetector()
4143
),
4244
new TableValidator(new SelectionInterpreter(false)),
4345
new TableViewModelFactory(new RowViewModelFactory(

package-lock.json

Lines changed: 99 additions & 83 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "markdown-table-prettify",
33
"displayName": "Markdown Table Prettifier",
44
"description": "Transforms markdown tables to be more readable.",
5-
"version": "3.1.0",
5+
"version": "3.2.0",
66
"publisher": "darkriszty",
77
"repository": {
88
"type": "git",
@@ -16,7 +16,12 @@
1616
"vscode": "^1.50.0"
1717
},
1818
"categories": [
19-
"Other"
19+
"Formatters"
20+
],
21+
"keywords": [
22+
"markdown",
23+
"table",
24+
"formatter"
2025
],
2126
"activationEvents": [
2227
"onLanguage:markdown"

src/extension/prettyfierFactory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { PadCalculatorSelector } from '../padCalculation/padCalculatorSelector';
2121
import { AlignmentMarkerStrategy } from '../viewModelFactories/alignmentMarking';
2222
import { MultiTablePrettyfier } from '../prettyfiers/multiTablePrettyfier';
2323
import { SingleTablePrettyfier } from '../prettyfiers/singleTablePrettyfier';
24+
import { FairTableIndentationDetector } from '../modelFactory/tableIndentationDetector';
2425

2526
export function getDocumentRangePrettyfier() {
2627
return new TableDocumentRangePrettyfier(getMultiTablePrettyfier());
@@ -50,7 +51,8 @@ function getSingleTablePrettyfier(loggers: ILogger[], sizeLimitCheker: ConfigSiz
5051
new TableFactory(
5152
new AlignmentFactory(),
5253
new SelectionInterpreter(false),
53-
new TrimmerTransformer(new BorderTransformer(null))
54+
new TrimmerTransformer(new BorderTransformer(null)),
55+
new FairTableIndentationDetector()
5456
),
5557
new TableValidator(new SelectionInterpreter(false)),
5658
new TableViewModelFactory(new RowViewModelFactory(

src/modelFactory/tableFactory.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { AlignmentFactory } from "./alignmentFactory";
33
import { Alignment } from "../models/alignment";
44
import { Transformer } from "./transformers/transformer";
55
import { SelectionInterpreter } from "./selectionInterpreter";
6+
import { TableIndentationDetector } from "./tableIndentationDetector";
67
import { Cell } from "../models/cell";
78
import { Line } from "../models/doc/line";
89
import { Row } from "../models/row";
@@ -14,11 +15,12 @@ export class TableFactory {
1415
constructor(
1516
private _alignmentFactory: AlignmentFactory,
1617
private _selectionInterpreter: SelectionInterpreter,
17-
private _transformer: Transformer)
18+
private _transformer: Transformer,
19+
private _tableIndentationDetector: TableIndentationDetector)
1820
{ }
1921

2022
public getModel(document: Document, range: Range): Table {
21-
const lines = document.getLines(range);
23+
const lines: Line[] = document.getLines(range);
2224
if (lines == null || lines.length == 0)
2325
throw new Error("Can't create table model from no lines.");
2426

@@ -38,6 +40,8 @@ export class TableFactory {
3840
? this._alignmentFactory.createAlignments(separator)
3941
: [];
4042

41-
return this._transformer.process(new Table(rowsWithoutSeparator, separatorLine.EOL, alignments));
43+
const leftPad: string = this._tableIndentationDetector.getLeftPad(lines.map(l => l.value));
44+
45+
return this._transformer.process(new Table(rowsWithoutSeparator, separatorLine.EOL, alignments, leftPad));
4246
}
4347
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
export abstract class TableIndentationDetector {
2+
protected abstract hasIndentation(leftPadsPerLine: string[]): boolean;
3+
protected abstract getIndentationChars(leftPadsPerLine: string[]): string;
4+
5+
public getLeftPad(lines: string[]): string {
6+
const leftPadsPerLine: string[] = lines.map(l => l.match(/^\s*/)[0]);
7+
8+
return this.hasIndentation(leftPadsPerLine)
9+
? this.getIndentationChars(leftPadsPerLine)
10+
: "";
11+
}
12+
}
13+
14+
/**
15+
* If more than half of the lines have indentation, assume indentation was intended.
16+
* Use the indentation characters used by the majority of the lines.
17+
*/
18+
export class FairTableIndentationDetector extends TableIndentationDetector {
19+
20+
protected hasIndentation(leftPadsPerLine: string[]): boolean {
21+
const totalLines: number = leftPadsPerLine.length;
22+
const linesWithActualLeftPadding: number = leftPadsPerLine.filter(p => p.length > 0).length;
23+
24+
return linesWithActualLeftPadding >= totalLines / 2;
25+
}
26+
27+
protected getIndentationChars(leftPadsPerLine: string[]): string {
28+
const nonEmptyLeftPads = leftPadsPerLine.filter(l => l.length > 0);
29+
let indentCounters: Map<string, number> = new Map();
30+
31+
for (const leftPad of nonEmptyLeftPads) {
32+
let count = 1;
33+
if (indentCounters.has(leftPad)) {
34+
count += indentCounters.get(leftPad);
35+
}
36+
indentCounters.set(leftPad, ++count);
37+
}
38+
39+
// if there is an indentation used for at least 2 distinct lines, then use that, otherwise use the first line's indentation
40+
const indentWithMostRepeats = [...indentCounters.entries()].reduce((prev, curr) => curr[1] > prev[1] ? curr : prev)
41+
return indentWithMostRepeats[1] > 1
42+
? indentWithMostRepeats[0]
43+
: indentCounters[0];
44+
}
45+
}

src/modelFactory/transformers/borderTransformer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ export class BorderTransformer extends Transformer {
1414
const rows: Row[] = this.rowsWithoutEmptyFirstAndLastColumn(input.rows, hasLeftBorder, hasRightBorder);
1515
const alignments = this.alignmentsWithoutEmptyFirstAndLastColumn(input.alignments, hasLeftBorder, hasRightBorder);
1616

17-
let result = new Table(rows, input.separatorEOL, alignments);
17+
const leftPad = hasLeftBorder
18+
? input.leftPad
19+
: "";
20+
let result = new Table(rows, input.separatorEOL, alignments, leftPad);
1821
result.hasLeftBorder = hasLeftBorder;
1922
result.hasRightBorder = this.hasRightBorder(hasLeftBorder, hasRightBorder);
2023
return result;

src/modelFactory/transformers/transformer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export abstract class Transformer {
77
protected abstract transform(input: Table): Table;
88

99
public process(input: Table): Table {
10+
//Note: consider dropping the transformers and moving all table related logic inside the factory.
1011
if (input == null || input.isEmpty())
1112
return input;
1213

src/modelFactory/transformers/trimmerTransformer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Table } from "../../models/table";
66
export class TrimmerTransformer extends Transformer {
77

88
public transform(input: Table): Table {
9-
return new Table(this.trimColumnValues(input.rows), input.separatorEOL, input.alignments);
9+
return new Table(this.trimColumnValues(input.rows), input.separatorEOL, input.alignments, input.leftPad);
1010
}
1111

1212
private trimColumnValues(rows: Row[]): Row[] {

0 commit comments

Comments
 (0)