DEV Community

Pacharapol Withayasakpunt
Pacharapol Withayasakpunt

Posted on

Pretty printing objects with multiline strings in terminal with colors

If you have use JavaScript for some time, you should notice that pretty printing JSON in Node.js is as simple as JSON.stringify(obj, null, 2).

(Also, if you need multiline strings, there is js-yaml.)

  • But there is never coloring

An alternative is console.log, which in Node.js, it is not as interactive as web browsers with Chrome DevTools, and the depth in by default limited to 2.

  • How do you maximize depths?
    • Easy, use console.dir(obj, { depth: null }) -- console.dir

BTW, in my test project, I got this,

inspect-basic

Even with proper options ({ depth: null, breakLength: Infinity, compact: false }), I still get this

inspect-custom

So, what's the solution?

You can customize inspect by providing your own class.

import util from 'util'

class MultilineString {
  // eslint-disable-next-line no-useless-constructor
  constructor (public s: string) {}

  [util.inspect.custom] (depth: number, options: util.InspectOptionsStylized) {
    return [
      '',
      ...this.s.split('\n').map((line) => {
        return '\x1b[2m|\x1b[0m ' + options.stylize(line, 'string')
      })
    ].join('\n')
  }
}
Enter fullscreen mode Exit fullscreen mode

(BTW, worry about \x1b[2m? It is How to change node.js's console font color?)

And, replace every instance of multiline string with the class.

function cloneAndReplace (obj: any) {
  if (obj && typeof obj === 'object') {
    if (Array.isArray(obj) && obj.constructor === Array) {
      const o = [] as any[]
      obj.map((el, i) => {
        o[i] = cloneAndReplace(el)
      })
      return o
    } else if (obj.constructor === Object) {
      const o = {} as any
      Object.entries(obj).map(([k, v]) => {
        o[k] = cloneAndReplace(v)
      })
      return o
    }
  } else if (typeof obj === 'string') {
    if (obj.includes('\n')) {
      return new MultilineString(obj)
    }
  }

  return obj
}

export function pp (obj: any, options: util.InspectOptions = {}) {
  console.log(util.inspect(cloneAndReplace(obj), {
    colors: true,
    depth: null,
    ...options
  }))
}
Enter fullscreen mode Exit fullscreen mode

Now the pretty printing function is ready to go.

pp

If you only need the pretty printing function, I have provided it here.

GitHub logo patarapolw / prettyprint

prettyprint beyond `JSON.stringify(obj, null, 2)` -- Multiline strings and colors

I also made it accessible via CLI, and possibly other programming languages, such as Python (via JSON / safeEval, actually).

Top comments (1)

Collapse
 
waylonwalker profile image
Waylon Walker

Thanks for sharing. That Stack Overflow post with all of the colors listed out is very handy. I don't do a ton of node.js. I use a lot of python in the back end and really like the colorama package.