truwrap

Smarter terminal text wrapping (handles 24bit color)

Usage no npm install needed!

<script type="module">
  import truwrap from 'https://cdn.skypack.dev/truwrap';
</script>

README

truwrap

A node module for text wrapping into streams that supports 24bit color SGR codes.

Publishing Status

npm Libraries.io
Travis Rollup

Development Status

Travis Libraries.io
Snyk Code-Climate Code-Climate Coverage

Documentation/Help

Twitter

v4 Breaking change The CLI command has been seperated into it's own repo truwrap-cli

Many current tty text wrapping solutions have issues with the 'long' and currently 'non-standard' RGB SGR codes (i.e ^[[38;2;204;51;66m). This meant that, while it's possible to have wonderful, rich, full gamut colours and the aesthetic data visualisations it entails, it comes at the price of painful typography and corrupted console displays as text is broken up, unnaturally wrapped and becoming unreadable as the SGR codes are dashed against the rocks of 1980's shortsightedness, confusing your terminal and ever so slightly breaking the heart of design aware coders and administrators everywhere.

Clearly this is unnacceptable!

Previously, the only solution was to take a last, long whistful look at how great console colour could be, before going back to the, at best, 256 colours of the xterm pallette, with it's lack of useful greens and overly dark purples, or, for some, the even more cruelly devastating 16 colours of the ansi pallette, before heading to the stationary cupboard for a bit of a cry.

But weep no more!

Developed as part of our internal data visualisation system, where having the fidelity of 24 bit colour and embedded images (currently macOS iTerm only) was a huge advantage.

Usage

Installation

npm install --save @thebespokepixel/truwrap
import {truwrap} from '@thebespokepixel/truwrap'

var writer = truwrap({
  left: 2,
  right: 2,
  mode: 'soft',
  outStream: process.stderr
})

var contentWidth = writer.getWidth()

writer.write("Some text to write...", "...and some more.")
writer.write("A new paragraph, if not implicitly present.")
writer.end() // Close the stream

mode can be set to the following values:

  • soft: words are broken before the column width, giving a left justified appearance.
  • hard: words are split at the column width.
  • keep: lines longer than the column width are kept.
  • container: left and right margins are ignored, giving a full width line.

As outStream was specified, wrapped output is written directly to the stream.

Images

If your terminal suppots them, you can add images into the wrapped output text.

To ensure that images are not used by default you need to set the env var TERM_IMAGES=enabled in your shell. See term-ng for details.

import {truwrap, createImage} from '@thebespokepixel/truwrap'

const image = createImage({
  name: 'test',
  file: join(dirname(fileURLToPath(import.meta.url)), '../media/test.png'),
  width: 'auto', // Number of chars wide you'd like image. 'auto' to take it from the image/set height.
  height: 1,     // Number of lines the image will take
  space: '   '   // A text string that is printed under the image so you can flow the wrapped text around it.
})

var renderer = truwrap({
  mode: 'container'
})

truwrap.write(image.render({
  nobreak: true,  // Don't add a linebreak after the image.
  stretch: false, // If true, distort the image the image to fit the width/height
  align: 1        // How many lines to move back up after printing the image.
  spacing: ' '    // A string to print after realigning the cursor after printing the image.
}))

console.log(truwrap.end())

As no outStream was specified truwrap.end() returns the wrapped text.

Panels

import {truwrap, parsePanel} from '@thebespokepixel/truwrap'

var writer = truwrap({
  left: 2,
  right: 2,
  mode: 'soft',
  outStream: process.stderr
})

const panelSource = parsePanel(
  'One|Two|Three|Four', //Input text with column delimiters
  '|',                  // Column delimiter
  writer.getWidth()     // Total width (chars) to make columns across
)

const panelOptions = {
  maxLineWidth: writer.getWidth(),    // Maximum line width
  showHeaders: false,                 // Show colum headers
  truncate: false,                    // Truncate columns if too wide
  config: panelSource.configuration   // Get config information from parsePanel()
}

writer.panel(panelSource.content, panelOptions)
writer.end() //Close stream

Related

For advanced 24bit colour handling see thebespokepixel/trucolor and npm trucolor.

Documentation

Full documentation can be found at https://thebespokepixel.github.io/truwrap/