alexeyraspopov/picocolors

Colors do not work in browser console

nathanbabcock opened this issue · 2 comments

The readme claims browser support; however it seems this is a bit of a bait-and-switch. The .browser.js version does nothing and is hardcoded for every function just to return strings unchanged. Looking through the previous issues I understand the reasoning for this, which is to support certain bundlers which were throwing errors.

Working version

Here is a picocolors.ts that works in the Chrome dev console. The only thing I've changed is to delete the isColorSupported function at the top which uses the Node tty module. Also I converted it to Typescript so I can easily move it between projects in a single file.

// picocolors.ts

const formatter =
  (open: string, close: string, replace = open) =>
  (input: string | number | null | undefined) => {
    const string = '' + input
    const index = string.indexOf(close, open.length)
    return ~index
      ? open + replaceClose(string, close, replace, index) + close
      : open + string + close
  }

const replaceClose = (
  string: string,
  close: string,
  replace: string,
  index: number
): string => {
  const start = string.substring(0, index) + replace
  const end = string.substring(index + close.length)
  const nextIndex = end.indexOf(close)
  return ~nextIndex
    ? start + replaceClose(end, close, replace, nextIndex)
    : start + end
}

let createColors = (enabled = true) => ({
  isColorSupported: enabled,
  reset: enabled ? (s: string) => `\x1b[0m${s}\x1b[0m` : String,
  bold: enabled ? formatter('\x1b[1m', '\x1b[22m', '\x1b[22m\x1b[1m') : String,
  dim: enabled ? formatter('\x1b[2m', '\x1b[22m', '\x1b[22m\x1b[2m') : String,
  italic: enabled ? formatter('\x1b[3m', '\x1b[23m') : String,
  underline: enabled ? formatter('\x1b[4m', '\x1b[24m') : String,
  inverse: enabled ? formatter('\x1b[7m', '\x1b[27m') : String,
  hidden: enabled ? formatter('\x1b[8m', '\x1b[28m') : String,
  strikethrough: enabled ? formatter('\x1b[9m', '\x1b[29m') : String,
  black: enabled ? formatter('\x1b[30m', '\x1b[39m') : String,
  red: enabled ? formatter('\x1b[31m', '\x1b[39m') : String,
  green: enabled ? formatter('\x1b[32m', '\x1b[39m') : String,
  yellow: enabled ? formatter('\x1b[33m', '\x1b[39m') : String,
  blue: enabled ? formatter('\x1b[34m', '\x1b[39m') : String,
  magenta: enabled ? formatter('\x1b[35m', '\x1b[39m') : String,
  cyan: enabled ? formatter('\x1b[36m', '\x1b[39m') : String,
  white: enabled ? formatter('\x1b[37m', '\x1b[39m') : String,
  gray: enabled ? formatter('\x1b[90m', '\x1b[39m') : String,
  bgBlack: enabled ? formatter('\x1b[40m', '\x1b[49m') : String,
  bgRed: enabled ? formatter('\x1b[41m', '\x1b[49m') : String,
  bgGreen: enabled ? formatter('\x1b[42m', '\x1b[49m') : String,
  bgYellow: enabled ? formatter('\x1b[43m', '\x1b[49m') : String,
  bgBlue: enabled ? formatter('\x1b[44m', '\x1b[49m') : String,
  bgMagenta: enabled ? formatter('\x1b[45m', '\x1b[49m') : String,
  bgCyan: enabled ? formatter('\x1b[46m', '\x1b[49m') : String,
  bgWhite: enabled ? formatter('\x1b[47m', '\x1b[49m') : String,
})

export default createColors()

I would happily open a PR to replace the stub version with this (or the JS equivalent), assuming this project is not abandoned...

I've added a PR to fix this. In the mean time, here's a fork: picocolors-browser.

Browser support means bundlers don't break if you accidentally ship this package to a browser. The suggested implementation only works in Chrome, which is not the Web. I'm happy to revisit this when Safari and Firefox support this too.