markdown-table-ts
Version:
A zero-dependency library for generating Markdown tables written in TypeScript.
148 lines (147 loc) • 5.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMarkdownTable = exports.MarkdownTableError = exports.Align = void 0;
var Align;
(function (Align) {
Align["Left"] = "left";
Align["Right"] = "right";
Align["Center"] = "center";
Align["None"] = "none";
})(Align || (Align = {}));
exports.Align = Align;
class MarkdownTableError extends Error {
constructor(m) {
super(m);
Object.setPrototypeOf(this, MarkdownTableError.prototype);
}
}
exports.MarkdownTableError = MarkdownTableError;
const validateTable = (table) => {
if (!table) {
throw new MarkdownTableError('Missing \'table\' property.');
}
if (!(table.head instanceof Array)) {
throw new MarkdownTableError(`Expected table.head to be Array<Column>, got ${typeof table.head}`);
}
if (table.head.length < 1) {
throw new MarkdownTableError(`Expected table to have at least 1 header, got ${table.head.length}`);
}
if (!(table.body instanceof Array)) {
throw new MarkdownTableError(`Expected table.body to be Array<Row>, got ${typeof table.body}`);
}
const allRows = [table.head, ...table.body];
allRows.forEach((row, rowIndex) => {
if (!(row instanceof Array)) {
throw new MarkdownTableError(`Expected row ${rowIndex} to be Array<string>, got ${typeof row}.`);
}
row.forEach((column, columnIndex) => {
if (typeof column !== 'string') {
throw new MarkdownTableError(`Expected column ${columnIndex} on row ${rowIndex} to be string, got ${typeof column}.`);
}
});
});
};
const validateAlignment = (alignment) => {
if (!alignment) {
return;
}
if (!(alignment instanceof Array)) {
throw new MarkdownTableError(`Expected alignment to be undefined or Array<Align>, got ${typeof alignment}.`);
}
alignment.forEach((a, index) => {
if (!Object.values(Align).includes(a)) {
throw new MarkdownTableError(`Invalid alignment for column ${index}.`);
}
});
};
const validateGetTableInput = (params) => {
if (!params) {
throw new MarkdownTableError('Missing input parameters.');
}
validateTable(params.table);
validateAlignment(params.alignment);
if (typeof params.alignColumns !== 'undefined' && typeof params.alignColumns !== 'boolean') {
throw new MarkdownTableError(`'alignColumns' must be either undefined or boolean, got ${typeof params.alignColumns}.`);
}
};
const getMarkdownRow = (params) => {
const alignment = params.alignment ? params.alignment : [];
let markdownRow = '|';
for (let i = 0; i < params.columnsAmount; i += 1) {
const column = params.row[i] ? params.row[i] : '';
const isRight = alignment[i] === Align.Right;
const isCenter = alignment[i] === Align.Center;
const targetLength = params.columnLengths ? params.columnLengths[i] : column.length;
if (isRight) {
markdownRow += ` ${column.padStart(targetLength)} |`;
}
else if (isCenter) {
markdownRow += ` ${column.padStart((targetLength + column.length) / 2).padEnd(targetLength)} |`;
}
else {
markdownRow += ` ${column.padEnd(targetLength)} |`;
}
}
return markdownRow;
};
const getMarkdownAlignment = (params) => {
const alignment = params.alignment ? params.alignment : [];
let markdownAlignment = '|';
for (let i = 0; i < params.columnsAmount; i += 1) {
const isLeft = alignment[i] === Align.Left;
const isRight = alignment[i] === Align.Right;
const isCenter = alignment[i] === Align.Center;
const isLeftOrCenter = isLeft || isCenter;
const isRightOrCenter = isRight || isCenter;
const targetLength = params.columnLengths ? params.columnLengths[i] - 2 : 1;
markdownAlignment += isLeftOrCenter ? ' :' : ' -';
markdownAlignment += '-'.padEnd(targetLength, '-');
markdownAlignment += isRightOrCenter ? ': |' : '- |';
}
return markdownAlignment;
};
const getColumnLengths = (params) => {
const columnLengths = new Array(params.maxColumnsAmount).fill(3);
for (let row = 0; row < params.allRows.length; row += 1) {
for (let column = 0; column < params.allRows[row].length; column += 1) {
columnLengths[column] = Math.max(columnLengths[column], params.allRows[row][column].length);
}
}
return columnLengths;
};
const getMarkdownTable = (params) => {
validateGetTableInput(params);
const headerColumns = params.table.head.length;
const rowColumns = params.table.body.map((row) => row.length);
const maxColumnsAmount = Math.max(headerColumns, ...rowColumns);
const alignColumns = params.alignColumns ?? true;
const columnLengths = alignColumns
? getColumnLengths({
allRows: [params.table.head, ...params.table.body],
maxColumnsAmount,
})
: undefined;
const markdownTableHead = getMarkdownRow({
alignment: params.alignment,
row: params.table.head,
columnsAmount: maxColumnsAmount,
columnLengths,
});
const markdownTableAlignment = getMarkdownAlignment({
alignment: params.alignment,
columnsAmount: maxColumnsAmount,
columnLengths,
});
let markdownTableBody = '';
params.table.body.forEach((row) => {
const markdownRow = getMarkdownRow({
alignment: params.alignment,
row,
columnsAmount: maxColumnsAmount,
columnLengths,
});
markdownTableBody += `${markdownRow}\n`;
});
return `${markdownTableHead}\n${markdownTableAlignment}\n${markdownTableBody}`.trimEnd();
};
exports.getMarkdownTable = getMarkdownTable;