fancy.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import stringWidth from 'string-width'
  2. import figures from 'figures'
  3. import chalk from 'chalk'
  4. import BasicReporter from './basic'
  5. import { parseStack } from '../utils/error'
  6. import { chalkColor, chalkBgColor } from '../utils/chalk'
  7. import { TYPE_COLOR_MAP, LEVEL_COLOR_MAP } from '../utils/fancy'
  8. const DEFAULTS = {
  9. secondaryColor: 'grey',
  10. formatOptions: {
  11. date: true,
  12. colors: true,
  13. compact: false
  14. }
  15. }
  16. const TYPE_ICONS = {
  17. info: figures('ℹ'),
  18. success: figures('✔'),
  19. debug: figures('›'),
  20. trace: figures('›'),
  21. log: ''
  22. }
  23. export default class FancyReporter extends BasicReporter {
  24. constructor (options) {
  25. super(Object.assign({}, DEFAULTS, options))
  26. }
  27. formatStack (stack) {
  28. const grey = chalkColor('grey')
  29. const cyan = chalkColor('cyan')
  30. return '\n' + parseStack(stack)
  31. .map(line => ' ' + line
  32. .replace(/^at +/, m => grey(m))
  33. .replace(/\((.+)\)/, (_, m) => `(${cyan(m)})`)
  34. )
  35. .join('\n')
  36. }
  37. formatType (logObj, isBadge) {
  38. const typeColor = TYPE_COLOR_MAP[logObj.type] ||
  39. LEVEL_COLOR_MAP[logObj.level] ||
  40. this.options.secondaryColor
  41. if (isBadge) {
  42. return chalkBgColor(typeColor).black(` ${logObj.type.toUpperCase()} `)
  43. }
  44. const _type = typeof TYPE_ICONS[logObj.type] === 'string' ? TYPE_ICONS[logObj.type] : (logObj.icon || logObj.type)
  45. return _type ? chalkColor(typeColor)(_type) : ''
  46. }
  47. formatLogObj (logObj, { width }) {
  48. const [message, ...additional] = this.formatArgs(logObj.args).split('\n')
  49. const isBadge = typeof logObj.badge !== 'undefined' ? Boolean(logObj.badge) : logObj.level < 2
  50. const secondaryColor = chalkColor(this.options.secondaryColor)
  51. const date = this.formatDate(logObj.date)
  52. const coloredDate = date && secondaryColor(date)
  53. const type = this.formatType(logObj, isBadge)
  54. const tag = logObj.tag ? secondaryColor(logObj.tag) : ''
  55. const formattedMessage = message.replace(/`([^`]+)`/g, (_, m) => chalk.cyan(m))
  56. let line
  57. const left = this.filterAndJoin([type, formattedMessage])
  58. const right = this.filterAndJoin([tag, coloredDate])
  59. const space = width - stringWidth(left) - stringWidth(right) - 2
  60. if (space > 0 && width >= 80) {
  61. line = left + ' '.repeat(space) + right
  62. } else {
  63. line = left
  64. }
  65. line += additional.length ? '\n' + additional.join('\n') : ''
  66. return isBadge ? '\n' + line + '\n' : line
  67. }
  68. }