Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions lib/css-syntax-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,14 @@ class CssSyntaxError extends Error {

let css = this.source
if (color == null) color = pico.isColorSupported

let highlightConditionally
if (terminalHighlight) {
if (color) css = terminalHighlight(css)
if (color) {
highlightConditionally = text => terminalHighlight(text)
} else {
highlightConditionally = text => text
}
}

let lines = css.split(/\r?\n/)
Expand All @@ -77,12 +83,27 @@ class CssSyntaxError extends Error {
let number = start + 1 + index
let gutter = ' ' + (' ' + number).slice(-maxWidth) + ' | '
if (number === this.line) {
if (line.length > 160) {
let padding = 20;
let subLineStart = Math.max(0, this.column - padding);
let subLineEnd = Math.max(this.column + padding, this.endColumn + padding);
let subLine = line.slice(subLineStart, subLineEnd)

let spacing =
aside(gutter.replace(/\d/g, ' ')) +
line.slice(0, Math.min(this.column - 1, padding - 1)).replace(/[^\t]/g, ' ')

return mark('>') + aside(gutter) + highlightConditionally(subLine) + '\n ' + spacing + mark('^')
}

let spacing =
aside(gutter.replace(/\d/g, ' ')) +
line.slice(0, this.column - 1).replace(/[^\t]/g, ' ')
return mark('>') + aside(gutter) + line + '\n ' + spacing + mark('^')

return mark('>') + aside(gutter) + highlightConditionally(line) + '\n ' + spacing + mark('^')
}
return ' ' + aside(gutter) + line

return ' ' + aside(gutter) + highlightConditionally(line)
})
.join('\n')
}
Expand Down
46 changes: 46 additions & 0 deletions test/css-syntax-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,52 @@ test('add leading space for line numbers', () => {
)
})

test('cut minified css', () => {
let css = '.a{position:absolute!important;clip:rect(1px,1px,1px,1px);}.b{border:0;background;text-decoration:none;font-size:100%;}.c{position:absolute!important;clip:rect(1px,1px,1px,1px);}.d{position:absolute!important;clip:rect(1px,1px,1px,1px);}'
is(
parseError(css).showSourceCode(false),
'> 1 | ,1px);}.b{border:0;background;text-decoration:none\n' +
' | ^'
)
})

test('correct mark position on cut minified css', () => {
let css = '.a{background;position:absolute!important;clip:rect(1px,1px,1px,1px);}.b{border:0;text-decoration:none;font-size:100%;}.c{position:absolute!important;clip:rect(1px,1px,1px,1px);}.d{position:absolute!important;clip:rect(1px,1px,1px,1px);}'
is(
parseError(css).showSourceCode(false),
'> 1 | .a{background;position:absolute!im\n' +
' | ^'
)
})

test('highlight cut minified css with colors', () => {
let css = '.a{position:absolute!important;clip:rect(1px,1px,1px,1px);}.b{border:0;background;text-decoration:none;font-size:100%;}.c{position:absolute!important;clip:rect(1px,1px,1px,1px);}.d{position:absolute!important;clip:rect(1px,1px,1px,1px);}'
is(
parseError(css).showSourceCode(true),
pico.bold(pico.red('>')) +
pico.gray(' 1 | ') +
',1px' +
pico.cyan(')') +
pico.yellow(';') +
pico.yellow('}') +
pico.yellow('.b') +
pico.yellow('{') +
'border' +
pico.yellow(':') +
'0' +
pico.yellow(';') +
'background' +
pico.yellow(';') + '' +
'text-decoration' +
pico.yellow(':') +
'none' +
'\n ' +
pico.gray(' | ') +
' ' +
pico.bold(pico.red('^'))
)
})

test('prints with highlight', () => {
is(
stripAnsi(parseError('a {').toString()),
Expand Down