ts-markdown
Version:
An extensible TypeScript markdown generator that takes JSON and creates a markdown document.
149 lines (148 loc) • 5.66 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.table = exports.tableRenderer = void 0;
const rendering_1 = require("../rendering");
/**
* The renderer for table entries.
*
* @param entry The table entry.
* @param options Document-level render options.
* @returns Block-level table markdown content.
*/
const tableRenderer = (entry, options) => {
if ('table' in entry) {
return {
markdown: getTableMarkdown(entry, options),
blockLevel: true,
};
}
throw new Error('Entry is not a table entry. Unable to render.');
};
exports.tableRenderer = tableRenderer;
function getTableMarkdown(entry, options) {
escapePipes(entry, entry.pipeReplacer);
let columnCount = entry.table.columns.length;
let columnNames = entry.table.columns.reduce((prev, curr) => prev.concat(typeof curr === 'string' ? curr : curr.name), []);
let minColumnWidth = 3;
let cellWidths = [];
for (let i = 0; i < columnCount; i++) {
let column = entry.table.columns[i];
let columnCellTexts = [
getColumnHeaderTextLength(entry.table.columns[i]),
...entry.table.rows
.reduce((prev, curr) => {
let value = Array.isArray(curr)
? curr[i]
: curr[getDataRowPropertyName(column)];
if (value !== undefined) {
let result = renderCellText(value, options, entry.prefixCellValues);
if (typeof result === 'string') {
prev.push(result);
}
else {
throw new Error('Unknown table rendering scenario encountered. Multi-line table cell content is not supported.');
}
}
return prev;
}, [])
.map((columnCellText) => columnCellText.length),
];
cellWidths[i] = columnCellTexts.reduce((prev, curr) => Math.max(minColumnWidth, prev, curr), 0);
}
return [
buildHeaderRow(entry, cellWidths, entry.table.columns),
buildDividerRow(cellWidths, entry.table.columns),
...buildDataRows(entry, cellWidths, entry.table.columns, options),
].join('\n');
}
function buildDataRows(entry, cellWidths, columns, options) {
return entry.table.rows.map((row) => {
let cells = [];
if (Array.isArray(row)) {
cells = [
...row.map((cell, index) => padAlign(renderCellText(cell, options, entry.prefixCellValues), cellWidths[index], entry.table.columns[index])),
];
}
else if (typeof row === 'object') {
cells = columns.reduce((prev, curr, index) => prev.concat(padAlign(renderCellText(row[getDataRowPropertyName(curr)], options, entry.prefixCellValues) ?? '', cellWidths[index], entry.table.columns[index])), []);
}
return `| ${cells.join(' | ')} |`;
});
}
function renderCellText(value, options, prefixCellValues = true) {
return (0, rendering_1.renderEntries)([value], {
...options,
prefix: prefixCellValues ? options.prefix : '',
});
}
function padAlign(cellText, cellWidth, column) {
return typeof column === 'string' || column.align === 'left' || !column.align
? cellText.padEnd(cellWidth, ' ')
: column.align === 'center'
? cellText
.padStart(cellText.length + Math.floor(cellWidth - cellText.length) / 2, ' ')
.padEnd(cellWidth, ' ')
: column.align === 'right'
? cellText.padStart(cellWidth, ' ')
: cellText;
}
function buildDividerRow(cellWidths, columns) {
return `|${cellWidths
.map((cellWidth, index) => getLeftSideAlignmentCharacter(columns[index]) +
''.padStart(cellWidth, '-') +
getRightSideAlignmentCharacter(columns[index]))
.join('|')}|`;
}
function getLeftSideAlignmentCharacter(column) {
if (typeof column === 'string') {
return ' ';
}
return column.align === 'left' || column.align === 'center' ? ':' : ' ';
}
function getRightSideAlignmentCharacter(column) {
if (typeof column === 'string') {
return ' ';
}
return column.align === 'right' || column.align === 'center' ? ':' : ' ';
}
function buildHeaderRow(entry, cellWidths, columns) {
return `| ${entry.table.columns
.map((column, index) => padAlign(getColumnName(column), cellWidths[index], columns[index]))
.join(' | ')} |`;
}
function getColumnName(column) {
return typeof column === 'string' ? column : column.name;
}
function getColumnHeaderTextLength(column) {
return typeof column === 'string' ? column.length : column.name.length;
}
function defaultPipeReplacer(content) {
return content.replaceAll('|', '|');
}
function escapePipes(target, pipeReplacer = defaultPipeReplacer) {
if (typeof target === 'string') {
return pipeReplacer(target);
}
if (Array.isArray(target)) {
for (let i = 0; i < target.length; i++) {
target[i] = escapePipes(target[i], pipeReplacer);
}
}
if (typeof target === 'object' && target !== null) {
let assignable = target;
for (let key of Object.keys(assignable)) {
assignable[key] = escapePipes(assignable[key], pipeReplacer);
}
}
return target;
}
function table(settings, options) {
return {
table: settings,
...options,
};
}
exports.table = table;
function getDataRowPropertyName(curr) {
return typeof curr === 'string' ? curr : curr.field ?? curr.name;
}