import { Value } from './Value'; import { split, trim } from './Collection'; import { FilterFunction } from './Filters'; import { NEWLINE, PIPE, SPACE } from './Predefined'; /** * split a list of Value instances into "cells" for every pipe character, * trim each value and extract the original value (if the original "cell" value * consisted of more than one Value, it will be joined as string) * * @param {Array} values * @returns {Array} */ function cells(values: Array): Array { return split(values, PIPE) .map((cell) => trim(cell, SPACE)) .map((cell) => cell.map(({ value }) => value)) .map((cell) => cell.length > 1 ? cell.join('') : cell[0]) } /** * split a list of Value instance into "rows" for every newline character * * @param {Array} values * @param {...Array} filters * @returns {Array>} */ function rows(values: Array, ...filters: Array): Array> { return split(values, NEWLINE) .map(cells) .filter((row) => filters.every((filter) => filter(...row))); } /** * Populate a list of values * * @template T * @param {Array} header * @param {Array>} list * @return {*} {Array} */ function populate(header: Array, list: Array>): Array { return list.map((values) => header.reduce((carry: T, name: unknown, index: number) => ({ ...carry, [String(name)]: values[index] }), Object.create(null) as T) ) as Array; } /** * turn a list of Value instances into a table structure (rows < cells) and turn * each row into a Record using the first row as key names * * @export * @template T * @param {Array} values * @param {...Array} filters * @returns {Array} */ export function records(values: Array, ...filters: Array): Array { const [header = [], ...lines] = rows(values, ...filters); const start = Number(typeof header[0] === 'undefined'); const end = Number(typeof header[header.length - 1] === 'undefined') * -1; return (start || end) ? populate(header.slice(start, end), lines.map((line) => line.slice(start, end))) : populate(header, lines); }