Skip to content

cto-af/linewrap

Repository files navigation

@cto.af/linewrap

Wrap lines using Unicode UAX #14 line breaking rules.

Installation

npm install @cto.af/linewrap

CLI

A command line interface is available: @cto.af/linewrap-cli

API

import {LineWrap} from '@cto.af/linewrap'
const w = new LineWrap()
w.wrap('Lorem ipsum dolor sit amet...')  // A string, wrapped to your console length
for (const line of w.lines('Lorem ipsum dolor sit amet...')) {
  // `line` does not have a newline at the end
}

Full API docs are available.

Methods

wrap(string)
Sometimes, you just want text out of the wrapping operation, with newlines between the lines. Use wrap() for this. Note that there is no newline at the end of the wrapped text.
*lines(string)
Sometimes, you'll want the lines individually; perhaps you're streaming, or integrating the lines with other content. The *lines() method will return a string generator, where each line is NOT ended with a newline. The wrap() method just calls *lines() and joins the result with your configured newline string.

Options

Options may be passed into the constructor in an object:

const w = new LineWrap({ width: 40 })

The following options are all optional, having the specified defaults:

ellipsis: string = '…' (U+2026: HORIZONTAL ELLIPSIS)
String to use when long word is truncated with LineWrap.OVERFLOW_CLIP.
example7: boolean = false
Turn on the extra rules for matching numbers from Example 7 of UAX #14
firstCol: number = NaN
If indentFirst is false, how many columns was the first line already indented? If NaN, use the indent width, in graphemes. If indentFirst is true, this is ignored.
hyphen: string = '-' (U+002D: HYPHEN-MINUS)
String to use when long word is split to next line with LineWrap.OVERFLOW_ANYWHERE.
indent: number | string = '' (empty string)
If a string, indent every line (except the first if indentFirst is false) with that string. If a number, insert that many indentChars at the beginning of each line.
includeANSI: boolean = false
If true, include ANSI escape sequences in the width of the string. If false, strips ANSI before calculating width.
indentChar: string = ' ' (U+0020: SPACE)
If indent is a number, use that many of this string to indent.
indentEmpty: boolean = false
If the input string is empty, should we still indent?
indentFirst : boolean = true
Indent the first line? If not, treat the first line as if it was already indented, giving a short first line. Use firstCol to control how short the first line should be.
isCJK : boolean
Override the locale, forcing strings to be measured in a Chinese/Japanese/Korean context or not.
isNewline : RegExp | null = /[^\S\r\n\v\f\x85\u2028\u2029]*[\r\n\v\f\x85\u2028\u2029]+\s*/gu
Regular expression that finds newlines for replacement with newlineReplacement. Ensure you do not create a regular expression denial of service (ReDoS) attack. Make sure the expression has the `g` modifier. If null, no newline replacement is done, and existing newlines will be maintained in the output, no matter where they were originally.
locale: string = [system locale as determined by Intl.Segmenter]
Which locale to use when splitting by graphemes? May have a small effect in some locales. If you have experience with one of those locales, please file an issue or PR with examples so this can be tested carefully.
newline: string = '\n'
String used to separate lines in the wrap() method.
newlineReplacement: string = ' '
For every newline found with isNewline, replace with this string.
overflow: Symbol = LineWrapOptions.OVERFLOW_VISIBLE
What to do with words that are longer than the available width? There are three options:
  • LineWrapOptions.OVERFLOW_VISIBLE: If a word is longer than the wrappable area, allow the word to go extend past the width so that it is not broken. This is the only way for long URLs to still be clickable.
  • LineWrapOptions.OVERFLOW_CLIP: If a word is longer than the wrappable area, cut it to size, dropping the rest of the word, inserting an ellipsis at the end.
  • LineWrapOptions.OVERFLOW_ANYWHERE: If a word is longer than the wrappable area, split it into chunks that do fit, inserting a hyphen at the end of each line.
verbose : boolean = false
Enable output on stdout for deep diagnostic information. Only useful for debugging.
width: number = 80
Maximum number of graphemes per line, including indentation.
escape: (x: string) => string = (x) => x
Function to escape the input string. The escaping is performed after line breaking and grapheme counting, with the intent that in the final display, those escapes will be replaced appropriately. Defaults to an identity transform.

Visual representation of options

Visual depiction of linewrap options


Tests codecov