diff --git a/docs/rules.md b/docs/rules.md index efe1076..85f8406 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -28,6 +28,10 @@ This is a descriptive standard for rules. The enforced meta-rules for rules [are Rules may be loaded from YAML or JSON files, using any extension. +| table | with | gap | row | +| ---- | -- | --- | - | +| foo | bar | bin | baz | + ### YAML Schema The default YAML schema has been extended with some custom types. diff --git a/src/reporter/TableReporter.ts b/src/reporter/TableReporter.ts index b2af312..48c05f8 100644 --- a/src/reporter/TableReporter.ts +++ b/src/reporter/TableReporter.ts @@ -1,11 +1,13 @@ -import { getOrDefault, leftPad, setOrPush } from '@apextoaster/js-utils'; +import { getOrDefault, leftPad, mustExist, mustGet, setOrPush } from '@apextoaster/js-utils'; import { Rule, RuleResult } from '../rule/index.js'; import { Reporter } from './index.js'; const MARGIN = ' '; const COL_DELIMITER = '|'; +const HEAD_DELIMITER = '-'; const ROW_DELIMITER = '\n'; +const EXTRA_ROWS = 2; interface RuleCounts { changes: number; @@ -31,6 +33,7 @@ export class TableReporter implements Reporter { return printTable(rows, ['rule', 'errors', 'changes'], { delimiter: { column: COL_DELIMITER, + head: HEAD_DELIMITER, row: ROW_DELIMITER, }, margin: MARGIN, @@ -42,6 +45,7 @@ export class TableReporter implements Reporter { export interface TableOptions { delimiter: { column: string; + head: string; row: string; }; margin: string; @@ -70,16 +74,25 @@ export function printTable(rows: Array, fields: Array, options: T } } - // get longest item in each + // get longest item in each column const lens = new Map(); - for (const [key, value] of cols) { - const max = value.reduce((p, c) => Math.max(p, c.length), 0); + for (const [key, values] of cols) { + const max = values.reduce((p, c) => Math.max(p, c.length), 0); lens.set(key, max); } + // add delimiter row + for (const field of fields) { + const max = mustGet(lens, field); + const gap = leftPad('', max, options.delimiter.head); + const col = mustGet(cols, field); + + col.splice(1, 0, gap); + } + // build table const parts = []; - for (let rowIndex = 0; rowIndex <= rows.length; ++rowIndex) { // <= because headers were added + for (let rowIndex = 0; rowIndex < rows.length + EXTRA_ROWS; ++rowIndex) { // <= because headers were added parts.push(options.delimiter.column); for (const [key, values] of cols) {