UNPKG

ts-markdown

Version:

An extensible TypeScript markdown generator that takes JSON and creates a markdown document.

149 lines (148 loc) 5.66 kB
"use strict"; 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('|', '&#124;'); } 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; }