All files / src/draw/align horizontally.ts

100% Statements 42/42
100% Branches 15/15
100% Functions 3/3
100% Lines 42/42

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  1x 1x 1x 1x 1x                           1x 1x 1747x 1747x 1747x   1747x 2447x   1064x 1064x   1064x 1064x 1064x 4426x 4426x 1064x 1064x 1064x     1343x 1343x 1343x 1343x 1343x 1343x 1343x 1343x 1343x 1343x 1343x 1343x 1343x 254x 254x 254x 1343x 1343x 1343x 1343x    
import type {EndoOf} from '#Function'
import {halfToFirst, halfToSecond} from '#Number'
import {stringWidth, widestLine} from '#String'
import {Array, pipe} from 'effect'
import {HStrut, HStruts} from '../struts.js'
import {matchHorizontal, type HorizontalAlignment} from './data.js'
 
/**
 * Align an array of single line strings according to the given alignment.
 * All strings in the returned array will be as wide as the widest among them.
 *
 * The given horizontal struts will be used to fill the available space created
 * by aligning the given parts.
 * @param hStruts Left and right horizontal struts will be used to fill available space.
 * @param hAlign A horizontal alignment will be used when not all shapes are of the same width.
 * @param useLeftRound Optional flag determining if remainder is added to the left or to the right the shape. By default it is `false` and the remainder is added to the _right_ of the shape.
 * @category drawing
 * @function
 */
export const alignHorizontally =
  (
    hStruts: HStruts,
    hAlign: HorizontalAlignment,
    useLeftRound = false,
  ): EndoOf<string[]> =>
  lines => {
    if (lines.length <= 1) return lines
 
    const available = widestLine(lines)
    const computeΔ = (line: string) => available - stringWidth(line)
 
    return pipe(
      lines,
      Array.map(line => {
        const Δ = computeΔ(line)
        return Δ <= 0 ? line : expand(hStruts, hAlign, Δ, useLeftRound)(line)
      }),
    )
  }
 
// Expand a line to fill available space according to given alignment.
function expand(
  struts: HStruts,
  alignment: HorizontalAlignment,
  Δ: number,
  useLeftRound: boolean,
): EndoOf<string> {
  const {left, right} = struts
  return line =>
    pipe(
      alignment,
      matchHorizontal(
        () => line + HStrut.fill(right)(Δ),
        () =>
          HStruts.fill(struts)(
            ...(useLeftRound ? halfToFirst : halfToSecond)(Δ),
          )(line),
        () => HStrut.fill(left)(Δ) + line,
      ),
    )
}
//