/node_modules/pretty-error/src/pretty-error.coffee
CoffeeScript | 309 lines | 228 code | 78 blank | 3 comment | 50 complexity | 7d819c42fbe94d4b15f57ae49e38df6d MD5 | raw file
- {object, array} = require 'utila'
- defaultStyle = require './default-style'
- ParsedError = require './parsed-error'
- nodePaths = require './node-paths'
- RenderKid = require 'renderkid'
- instance = null
- module.exports = class PrettyError
- self = @
- @_filters:
- 'module.exports': (item) ->
- return unless item.what?
- item.what = item.what.replace /\.module\.exports\./g, ' - '
- return
- @_getDefaultStyle: ->
- defaultStyle()
- @start: ->
- unless instance?
- instance = new self
- instance.start()
- instance
- @stop: ->
- instance?.stop()
- constructor: ->
- @_useColors = yes
- @_maxItems = 50
- @_packagesToSkip = []
- @_pathsToSkip = []
- @_skipCallbacks = []
- @_filterCallbacks = []
- @_parsedErrorFilters = []
- @_aliases = []
- @_renderer = new RenderKid
- @_style = self._getDefaultStyle()
- @_renderer.style @_style
- start: ->
- @_oldPrepareStackTrace = Error.prepareStackTrace
- prepeare = @_oldPrepareStackTrace or (exc, frames) ->
- result = exc.toString()
- frames = frames.map (frame) -> " at #{frame.toString()}"
- result + "\n" + frames.join "\n"
- # https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
- Error.prepareStackTrace = (exc, trace) =>
- stack = prepeare.apply(null, arguments)
- @render {stack, message: exc.toString().replace /^.*: /, ''}, no
- @
- stop: ->
- Error.prepareStackTrace = @_oldPrepareStackTrace
- @_oldPrepareStackTrace = null
- config: (c) ->
- if c.skipPackages?
- if c.skipPackages is no
- @unskipAllPackages()
- else
- @skipPackage.apply @, c.skipPackages
- if c.skipPaths?
- if c.skipPaths is no
- @unskipAllPaths()
- else
- @skipPath.apply @, c.skipPaths
- if c.skip?
- if c.skip is no
- @unskipAll()
- else
- @skip.apply @, c.skip
- if c.maxItems?
- @setMaxItems c.maxItems
- if c.skipNodeFiles is yes
- @skipNodeFiles()
- else if c.skipNodeFiles is no
- @unskipNodeFiles()
- if c.filters?
- if c.filters is no
- @removeAllFilters()
- else
- @filter.apply @, c.filters
- if c.parsedErrorFilters?
- if c.parsedErrorFilters is no
- @removeAllParsedErrorFilters()
- else
- @filterParsedError.apply @, c.parsedErrorFilters
- if c.aliases?
- if object.isBareObject c.aliases
- @alias path, alias for path, alias of c.aliases
- else if c.aliases is no
- @removeAllAliases()
- @
- withoutColors: ->
- @_useColors = false
- @
- withColors: ->
- @_useColors = true
- @
- skipPackage: (packages...) ->
- @_packagesToSkip.push String pkg for pkg in packages
- @
- unskipPackage: (packages...) ->
- array.pluckOneItem(@_packagesToSkip, pkg) for pkg in packages
- @
- unskipAllPackages: ->
- @_packagesToSkip.length = 0
- @
- skipPath: (paths...) ->
- @_pathsToSkip.push path for path in paths
- @
- unskipPath: (paths...) ->
- array.pluckOneItem(@_pathsToSkip, path) for path in paths
- @
- unskipAllPaths: ->
- @_pathsToSkip.length = 0
- @
- skip: (callbacks...) ->
- @_skipCallbacks.push cb for cb in callbacks
- @
- unskip: (callbacks...) ->
- array.pluckOneItem(@_skipCallbacks, cb) for cb in callbacks
- @
- unskipAll: ->
- @_skipCallbacks.length = 0
- @
- skipNodeFiles: ->
- @skipPath.apply @, nodePaths
- unskipNodeFiles: ->
- @unskipPath.apply @, nodePaths
- filter: (callbacks...) ->
- @_filterCallbacks.push cb for cb in callbacks
- @
- removeFilter: (callbacks...) ->
- array.pluckOneItem(@_filterCallbacks, cb) for cb in callbacks
- @
- removeAllFilters: ->
- @_filterCallbacks.length = 0
- @
- filterParsedError: (callbacks...) ->
- @_parsedErrorFilters.push cb for cb in callbacks
- @
- removeParsedErrorFilter: (callbacks...) ->
- array.pluckOneItem(@_parsedErrorFilters, cb) for cb in callbacks
- @
- removeAllParsedErrorFilters: ->
- @_parsedErrorFilters.length = 0
- @
- setMaxItems: (maxItems = 50) ->
- if maxItems is 0 then maxItems = 50
- @_maxItems = maxItems|0
- @
- alias: (stringOrRx, alias) ->
- @_aliases.push {stringOrRx, alias}
- @
- removeAlias: (stringOrRx) ->
- array.pluckByCallback @_aliases, (pair) ->
- pair.stringOrRx is stringOrRx
- @
- removeAllAliases: ->
- @_aliases.length = 0
- @
- _getStyle: ->
- @_style
- appendStyle: (toAppend) ->
- object.appendOnto @_style, toAppend
- @_renderer.style toAppend
- @
- _getRenderer: ->
- @_renderer
- render: (e, logIt = no, useColors = @_useColors) ->
- obj = @getObject e
- rendered = @_renderer.render(obj, useColors)
- console.error rendered if logIt is yes
- rendered
- getObject: (e) ->
- unless e instanceof ParsedError
- e = new ParsedError e
- @_applyParsedErrorFiltersOn e
- header =
- title: do ->
- ret = {}
- # some errors are thrown to display other errors.
- # we call them wrappers here.
- if e.wrapper isnt ''
- ret.wrapper = "#{e.wrapper}"
- ret.kind = e.kind
- ret
- colon: ':'
- message: String(e.message).trim()
- traceItems = []
- count = -1
- for item, i in e.trace
- continue unless item?
- continue if @_skipOrFilter(item, i) is yes
- count++
- break if count > @_maxItems
- if typeof item is 'string'
- traceItems.push item: custom: item
- continue
- traceItems.push item:
- header:
- pointer: do ->
- return '' unless item.file?
- file: item.file
- colon: ':'
- line: item.line
- what: item.what
- footer: do ->
- foooter = addr: item.shortenedAddr
- if item.extra? then foooter.extra = item.extra
- foooter
- obj = 'pretty-error':
- header: header
- if traceItems.length > 0
- obj['pretty-error'].trace = traceItems
- obj
- _skipOrFilter: (item, itemNumber) ->
- if typeof item is 'object'
- return yes if item.modName in @_packagesToSkip
- return yes if item.path in @_pathsToSkip
- for modName in item.packages
- return yes if modName in @_packagesToSkip
- if typeof item.shortenedAddr is 'string'
- for pair in @_aliases
- item.shortenedAddr = item.shortenedAddr.replace pair.stringOrRx, pair.alias
- for cb in @_skipCallbacks
- return yes if cb(item, itemNumber) is yes
- for cb in @_filterCallbacks
- cb(item, itemNumber)
- return no
- _applyParsedErrorFiltersOn: (error) ->
- for cb in @_parsedErrorFilters
- cb error
- return
- for prop in ['renderer', 'style'] then do ->
- methodName = '_get' + prop[0].toUpperCase() + prop.substr(1, prop.length)
- PrettyError::__defineGetter__ prop, -> do @[methodName]