All files / src/draw/part draw.ts

100% Statements 48/48
100% Branches 5/5
100% Functions 3/3
100% Lines 48/48

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 691x 1x 1x 1x 1x 1x 1x           1x 1x 1x   1x 1x 1x 1x 1x 1x                 1x     1x 1x 1x   596x 596x 596x 596x 596x 596x 596x 1x 1x   595x 595x 595x 595x 595x 595x 595x 595x 595x   595x 595x 595x 595x 595x 595x 595x   1097x 1097x 1097x  
import {K} from '#util'
import {flatten, map, transpose, type NonEmptyArray2} from '#Array'
import {unlines, unwords} from '#String'
import {Array, Option, pipe} from 'effect'
import {type Algebra} from 'effect-ts-folds'
import {alignHorizontally, alignVertically} from '../align.js'
import {
  matchPartF,
  type ColumnF,
  type PartFTypeLambda,
  type RowF,
} from '../partF.js'
import {normalizeStruts} from '../struts.js'
import {partCata} from './fold.js'
import {type Part} from './types.js'
 
const drawFold: Algebra<PartFTypeLambda, string[]> = matchPartF(
  [],
  Array.of,
  drawRowF,
  drawColumnF,
)
 
/**
 * Render a part into a list of strings rows.
 * @param part Part to be drawn.
 * @returns Possibly empty array of lines.
 * @category drawing
 * @function
 */
export const drawPart: {
  (part: Part): string[]
  unlines: (part: Part) => string
} = Object.assign(partCata(drawFold), {
  unlines: (part: Part): string => pipe(part, partCata(drawFold), unlines),
})
 
function drawRowF({
  hAlign,
  vAlign,
  cells: [cellsHead, ...cellsTail],
  ...struts
}: RowF<string[]>): string[] {
  if (cellsHead === undefined) {
    return []
  }
 
  const {left, right, top, bottom} = normalizeStruts(struts)
  const aligned = pipe(
    [cellsHead, ...cellsTail],
    alignVertically(
      {top, bottom},
      vAlign,
      alignHorizontally({left, right}, hAlign),
    ),
  ) as unknown as NonEmptyArray2<string>
 
  return pipe(
    aligned,
    transpose,
    map(map(Option.getOrElse(K(' ')))),
    map(unwords),
  )
}
 
function drawColumnF({cells, hAlign, ...hStruts}: ColumnF<string[]>): string[] {
  return pipe(cells, flatten, alignHorizontally(hStruts, hAlign))
}