css-syntax-error.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. 'use strict'
  2. let { red, bold, gray, options: colorette } = require('colorette')
  3. let terminalHighlight = require('./terminal-highlight')
  4. class CssSyntaxError extends Error {
  5. constructor(message, line, column, source, file, plugin) {
  6. super(message)
  7. this.name = 'CssSyntaxError'
  8. this.reason = message
  9. if (file) {
  10. this.file = file
  11. }
  12. if (source) {
  13. this.source = source
  14. }
  15. if (plugin) {
  16. this.plugin = plugin
  17. }
  18. if (typeof line !== 'undefined' && typeof column !== 'undefined') {
  19. this.line = line
  20. this.column = column
  21. }
  22. this.setMessage()
  23. if (Error.captureStackTrace) {
  24. Error.captureStackTrace(this, CssSyntaxError)
  25. }
  26. }
  27. setMessage() {
  28. this.message = this.plugin ? this.plugin + ': ' : ''
  29. this.message += this.file ? this.file : '<css input>'
  30. if (typeof this.line !== 'undefined') {
  31. this.message += ':' + this.line + ':' + this.column
  32. }
  33. this.message += ': ' + this.reason
  34. }
  35. showSourceCode(color) {
  36. if (!this.source) return ''
  37. let css = this.source
  38. if (color == null) color = colorette.enabled
  39. if (terminalHighlight) {
  40. if (color) css = terminalHighlight(css)
  41. }
  42. let lines = css.split(/\r?\n/)
  43. let start = Math.max(this.line - 3, 0)
  44. let end = Math.min(this.line + 2, lines.length)
  45. let maxWidth = String(end).length
  46. let mark, aside
  47. if (color) {
  48. mark = text => bold(red(text))
  49. aside = text => gray(text)
  50. } else {
  51. mark = aside = str => str
  52. }
  53. return lines
  54. .slice(start, end)
  55. .map((line, index) => {
  56. let number = start + 1 + index
  57. let gutter = ' ' + (' ' + number).slice(-maxWidth) + ' | '
  58. if (number === this.line) {
  59. let spacing =
  60. aside(gutter.replace(/\d/g, ' ')) +
  61. line.slice(0, this.column - 1).replace(/[^\t]/g, ' ')
  62. return mark('>') + aside(gutter) + line + '\n ' + spacing + mark('^')
  63. }
  64. return ' ' + aside(gutter) + line
  65. })
  66. .join('\n')
  67. }
  68. toString() {
  69. let code = this.showSourceCode()
  70. if (code) {
  71. code = '\n\n' + code + '\n'
  72. }
  73. return this.name + ': ' + this.message + code
  74. }
  75. }
  76. module.exports = CssSyntaxError
  77. CssSyntaxError.default = CssSyntaxError