UNPKG

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