thi-ng/umbrella

View on GitHub
packages/transducers/src/word-wrap.ts

Summary

Maintainability
A
0 mins
Test Coverage
import type { Transducer } from "./api.js";
import { __iter, iterator } from "./iterator.js";
import { partitionBy } from "./partition-by.js";

export interface WordWrapOpts {
    delim: number;
    always: boolean;
}

/**
 * Returns transducer partitioning words into variable sized arrays
 * based on given `lineLength` (default 80).
 *
 * @remarks
 * The optional `delim` and `always` args can be used to adjust the
 * length and usage of delimiters between each word. If `always` is
 * true, the delimiter length is added to each word, even near line
 * endings. If false (default), the last word on each line can still fit
 * even if there's no space for the delimiter.
 *
 * @param lineLength -
 * @param opts -
 */
export function wordWrap(
    lineLength: number,
    opts?: Partial<WordWrapOpts>
): Transducer<string, string[]>;
export function wordWrap(
    lineLength: number,
    src: Iterable<string>
): IterableIterator<string[]>;
export function wordWrap(
    lineLength: number,
    opts: Partial<WordWrapOpts>,
    src: Iterable<string>
): IterableIterator<string[]>;
export function wordWrap(...args: any[]): any {
    const iter = __iter(wordWrap, args, iterator);
    if (iter) {
        return iter;
    }
    const lineLength = args[0];
    const { delim = 1, always = true } = <WordWrapOpts>args[1];
    return partitionBy(() => {
        let n = 0;
        let flag = false;
        return (w: string) => {
            n += w.length + delim;
            if (n > lineLength + (always ? 0 : delim)) {
                flag = !flag;
                n = w.length + delim;
            }
            return flag;
        };
    }, true);
}