In Node.js why does piping to child_process.stdout to process.stdout strip ANSI colors?

Viewed 713

In node when I try and spawn a child process and then listen to stdout stream data and send it to process.stdout ansi colours are stripped:

// Will not preserve tty colors
const cp = spawn(procExec, ['--production'])
cp.stdout.on('data', (buf) => {
  // can manipulate buf
  process.stdout.write(buf)
});

cp.stderr.on('data', (buf) => {
  // can manipulate buf
  process.stderr.write(buf)
});
// Also will not preserve tty colors
const cp = spawn(procExec, ['--production'])
cp.stdout.pipe(process.stdout);
cp.stderr.pipe(process.stderr);

Looking through the node docs and the standard solution is to use the various possibilities for the stdio option:

const cp = spawn('ls', ['-l'], {
  stdio: 'inherit'
})

or

const cp = spawn('ls', ['-l'], {
  stdio: [0,1,2]
})

or

const cp = spawn('ls', ['-l'], {
  stdio: [process.stdin,process.stdout,process.stderr]
})

This WILL preserve ANSI colors in a terminal.

Normally this is fine however this means it is impossible to manipulate the output of the stream before it is sent to process.stdout or process.stderr.

a. Why does piping to child_process.stdout to process.stdout strip ANSI colors? Is it the same reason that listening to the data event does the same?

b. How can I both manipulate manipulate the output (ie. change the text) of the stream WHILST keeping the colors at the same time?

1 Answers

I am not an expert on these by any means but my take away from one of the answers in this thread is that node by default doesn't offer an actual tty stream when using spawn. Why? Because doing so is expensive and varies system by system and shell by shell. Instead it is maintained as a package for those that need it https://www.npmjs.com/package/node-pty This actually makes sense since it can be large and some users might not even have rights to get a tty shell and so they made non tty the default for spawn. It works for many cases and means less code for node core. At the end of the day it is probably worth just using that package if you need it. I don't know if you can modify the stream but if you do then you are going to need to deal with output that has ansi color codes in it which is trickier than just your standard string parsing.

Related