Skip to content

Commit

Permalink
Change to make report cleaner, prettier
Browse files Browse the repository at this point in the history
* Change to use a bit less white space
* Change to make the reason of messages bold
* Change to highlight markdown `code` in reason
  • Loading branch information
wooorm committed Jun 12, 2023
1 parent 16002e7 commit f987b52
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 34 deletions.
77 changes: 74 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,18 @@
* Regular style.
* @property {string} red
* Color.
* @property {string} cyan
* Color.
* @property {string} green
* Color.
* @property {string} yellow
* Color.
* @property {string} defaultColor
* Regular color.
*
* @typedef CodeSplit
* @property {number} index
* @property {number} size
*/

import stringWidth from 'string-width'
Expand All @@ -81,6 +87,7 @@ const eol = /\r?\n|\r/
* @returns {string}
* Report.
*/
// eslint-disable-next-line complexity
export function reporter(files, options) {
if (
// Nothing.
Expand Down Expand Up @@ -120,6 +127,7 @@ export function reporter(files, options) {
normalIntensity: colorEnabled ? '\u001B[22m' : '',
noUnderline: colorEnabled ? '\u001B[24m' : '',
red: colorEnabled ? '\u001B[31m' : '',
cyan: colorEnabled ? '\u001B[36m' : '',
green: colorEnabled ? '\u001B[32m' : '',
yellow: colorEnabled ? '\u001B[33m' : '',
defaultColor: colorEnabled ? '\u001B[39m' : ''
Expand Down Expand Up @@ -333,10 +341,9 @@ function createMessageLine(state, message) {
const place = message.place || message.position

const row = [
'',
stringifyPosition(place),
(label === 'error' ? state.red : state.yellow) + label + state.defaultColor,
reason,
formatReason(state, reason),
message.ruleId || '',
message.source || ''
]
Expand Down Expand Up @@ -433,6 +440,70 @@ function createUrlLines(state, url) {
]
}

/**
* Format a reason.
*
* @param {State} state
* Info passed around.
* @param {string} reason
* Reason.
* @returns {string}
* Result.
*/
function formatReason(state, reason) {
/** @type {Array<string>} */
const result = []
/** @type {Array<CodeSplit>} */
const splits = []
let index = reason.indexOf('`')

while (index !== -1) {
const split = {index, size: 1}
splits.push(split)

while (reason.codePointAt(index + 1) === 96) {
split.size++
index++
}

index = reason.indexOf('`', index + 1)
}

index = -1
let textStart = 0

while (++index < splits.length) {
let closeIndex = index
/** @type {CodeSplit | undefined} */
let close

while (++closeIndex < splits.length) {
if (splits[index].size === splits[closeIndex].size) {
close = splits[closeIndex]
break
}
}

if (close) {
const codeStart = splits[index].index
const codeEnd = close.index + close.size

result.push(
reason.slice(textStart, codeStart) +
state.cyan +
reason.slice(codeStart, codeEnd) +
state.defaultColor
)
textStart = codeEnd
index = closeIndex
}
}

result.push(reason.slice(textStart))

return state.bold + result.join('') + state.normalIntensity
}

/**
* Serialize `fatal` as a label.
*
Expand Down Expand Up @@ -489,7 +560,7 @@ function serializeRows(rows) {

while (++cellIndex < row.length) {
const cell = row[cellIndex] || ''
const max = (sizes[cellIndex] || 0) + 2
const max = (sizes[cellIndex] || 0) + 1
line += cell + ' '.repeat(max - stringWidth(cell))
}
}
Expand Down
71 changes: 40 additions & 31 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ test('reporter', async function () {
strip(reporter([file, new VFile({path: 'b.js'})])),
[
'a.js',
' warning Warning!',
' warning Warning!',
'',
'b.js: no issues found',
'',
Expand All @@ -129,7 +129,7 @@ test('reporter', async function () {
strip(reporter([file, new VFile({path: 'b.js'})])),
[
'a.js',
' error Error!',
' error Error!',
'',
'b.js: no issues found',
'',
Expand Down Expand Up @@ -157,12 +157,12 @@ test('reporter', async function () {
strip(reporter(file)),
[
'a.js',
' error Another error!',
' error Error!',
' warning Another warning!',
' warning Note!',
' warning Warning!',
' info Another note!',
' error Another error!',
' error Error!',
' warning Another warning!',
' warning Note!',
' warning Warning!',
' info Another note!',
'',
'6 messages (✖ 2 errors, ⚠ 3 warnings)'
].join('\n'),
Expand All @@ -173,12 +173,12 @@ test('reporter', async function () {
reporter(file, {color: false}),
[
'a.js',
' error Another error!',
' error Error!',
' warning Another warning!',
' warning Note!',
' warning Warning!',
' info Another note!',
' error Another error!',
' error Error!',
' warning Another warning!',
' warning Note!',
' warning Warning!',
' info Another note!',
'',
'6 messages (✖ 2 errors, ⚠ 3 warnings)'
].join('\n'),
Expand All @@ -190,7 +190,7 @@ test('reporter', async function () {

assert.equal(
strip(reporter(file)),
' warning Warning!\n\n⚠ 1 warning',
' warning Warning!\n\n⚠ 1 warning',
'should support a missing position'
)

Expand All @@ -199,7 +199,7 @@ test('reporter', async function () {

assert.equal(
strip(reporter(file)),
[' 3:2 warning Warning!', '', '⚠ 1 warning'].join('\n'),
['3:2 warning Warning!', '', '⚠ 1 warning'].join('\n'),
'should support a single point'
)

Expand All @@ -211,7 +211,7 @@ test('reporter', async function () {

assert.equal(
strip(reporter(file)),
[' 3:2-4:8 warning Warning!', '', '⚠ 1 warning'].join('\n'),
['3:2-4:8 warning Warning!', '', '⚠ 1 warning'].join('\n'),
'should support a location'
)

Expand All @@ -224,7 +224,7 @@ test('reporter', async function () {

assert.equal(
strip(reporter(file)),
['foo.bar', ' 3:2-4:8 warning Warning!', '', '⚠ 1 warning'].join('\n'),
['foo.bar', '3:2-4:8 warning Warning!', '', '⚠ 1 warning'].join('\n'),
'should support a location (#2)'
)

Expand All @@ -238,7 +238,7 @@ test('reporter', async function () {
cleanStack(strip(reporter(file)), 3),
[
'test.js',
' error ReferenceError: variable is not defined',
' error ReferenceError: variable is not defined',
' at test.js:1:1'
].join('\n'),
'should support a “real” error (show a stack)'
Expand All @@ -254,7 +254,7 @@ test('reporter', async function () {
cleanStack(strip(reporter(file)), 3),
[
'test.js',
' error ReferenceError: variable is not defined bar foo',
' error ReferenceError: variable is not defined bar foo',
' at test.js:1:1'
].join('\n'),
'should properly align a real error with a source'
Expand All @@ -268,7 +268,7 @@ test('reporter', async function () {

assert.equal(
cleanStack(strip(reporter(file)), 3),
'test.js\n error ReferenceError: foo\n at test.js:1:1',
'test.js\n error ReferenceError: foo\n at test.js:1:1',
'should support a “real” error with a changed message'
)

Expand All @@ -282,7 +282,7 @@ test('reporter', async function () {
cleanStack(strip(reporter(file)), 5),
[
'test.js',
' error ReferenceError: foo',
' error ReferenceError: foo',
'bar',
'baz',
' at test.js:1:1'
Expand All @@ -300,7 +300,7 @@ test('reporter', async function () {
cleanStack(strip(reporter(file)), 5),
[
'test.js',
' error ReferenceError: foo bravo alpha',
' error ReferenceError: foo bravo alpha',
'bar',
'baz',
' at test.js:1:1'
Expand All @@ -313,7 +313,7 @@ test('reporter', async function () {

assert.equal(
strip(reporter([file, new VFile({path: 'b.js'})], {quiet: true})),
['a.js', ' warning Warning!', '', '⚠ 1 warning'].join('\n'),
['a.js', ' warning Warning!', '', '⚠ 1 warning'].join('\n'),
'should ignore successful files in `quiet` mode'
)

Expand All @@ -328,7 +328,7 @@ test('reporter', async function () {

assert.equal(
strip(reporter([file, fileB], {silent: true})),
['a.js', ' error Error!', '', '✖ 1 error'].join('\n'),
['a.js', ' error Error!', '', '✖ 1 error'].join('\n'),
'should ignore non-failures in `silent` mode'
)

Expand Down Expand Up @@ -402,7 +402,7 @@ test('reporter', async function () {
assert.equal(
strip(reporter(file)),
[
' warning Something failed terribly',
' warning Something failed terribly',
' [cause]:',
' ReferenceError: variable is not defined',
' at test.js:1:1',
Expand Down Expand Up @@ -442,14 +442,14 @@ test('reporter', async function () {

assert.equal(
strip(reporter(file)),
' warning x\n\n⚠ 1 warning',
' warning x\n\n⚠ 1 warning',
'should not show `message.ancestors` in normal mode'
)

assert.equal(
strip(reporter(file, {verbose: true})),
[
' warning x',
' warning x',
' [trace]:',
' at text',
' at mdxJsxTextElement<b>',
Expand All @@ -464,7 +464,7 @@ test('reporter', async function () {
assert.equal(
strip(reporter(file, {verbose: true, traceLimit: 2})),
[
' warning x',
' warning x',
' [trace]:',
' at text',
' at mdxJsxTextElement<b>',
Expand All @@ -480,7 +480,7 @@ test('reporter', async function () {
assert.equal(
strip(reporter(file, {verbose: true})),
[
' warning Alpha',
' warning Alpha',
' [note]:',
' Bravo',
' charlie.',
Expand All @@ -496,14 +496,23 @@ test('reporter', async function () {
assert.equal(
strip(reporter(file, {verbose: true})),
[
' warning Alpha',
' warning Alpha',
' [url]:',
' https://example.com',
'',
'⚠ 1 warning'
].join('\n'),
'should support `message.url` in verbose mode'
)

file = new VFile()
file.message('a `b` c `` d `` e `` f ` g `` h ```')

assert.equal(
reporter(file),
' \u001B[33mwarning\u001B[39m \u001B[1ma \u001B[36m`b`\u001B[39m c \u001B[36m`` d ``\u001B[39m e \u001B[36m`` f ` g ``\u001B[39m h ```\u001B[22m\n\n\u001B[33m⚠\u001B[39m 1 warning',
'should highlight markdown code in message reasons'
)
})

/**
Expand Down

0 comments on commit f987b52

Please sign in to comment.