rsnext/packages/next/lib/eslint/customFormatter.ts

137 lines
3.1 KiB
TypeScript

import chalk from 'next/dist/compiled/chalk'
import path from 'path'
// eslint-disable-next-line no-shadow
export enum MessageSeverity {
Warning = 1,
Error = 2,
}
interface LintMessage {
ruleId: string | null
severity: 1 | 2
message: string
line: number
column: number
}
export interface LintResult {
filePath: string
messages: LintMessage[]
errorCount: number
warningCount: number
output?: string
source?: string
}
function pluginCount(messages: LintMessage[]): {
nextPluginErrorCount: number
nextPluginWarningCount: number
} {
let nextPluginWarningCount = 0
let nextPluginErrorCount = 0
for (let i = 0; i < messages.length; i++) {
const { severity, ruleId } = messages[i]
if (ruleId?.includes('@next/next')) {
if (severity === MessageSeverity.Warning) {
nextPluginWarningCount += 1
} else {
nextPluginErrorCount += 1
}
}
}
return {
nextPluginErrorCount,
nextPluginWarningCount,
}
}
function formatMessage(
dir: string,
messages: LintMessage[],
filePath: string
): string {
let fileName = path.posix.normalize(
path.relative(dir, filePath).replace(/\\/g, '/')
)
if (!fileName.startsWith('.')) {
fileName = './' + fileName
}
let output = '\n' + chalk.cyan(fileName)
for (let i = 0; i < messages.length; i++) {
const { message, severity, line, column, ruleId } = messages[i]
output = output + '\n'
if (line && column) {
output =
output +
chalk.yellow(line.toString()) +
':' +
chalk.yellow(column.toString()) +
' '
}
if (severity === MessageSeverity.Warning) {
output += chalk.yellow.bold('Warning') + ': '
} else {
output += chalk.red.bold('Error') + ': '
}
output += message
if (ruleId) {
output += ' ' + chalk.gray.bold(ruleId)
}
}
return output
}
export function formatResults(
baseDir: string,
results: LintResult[],
format: (r: LintResult[]) => string
): {
output: string
totalNextPluginErrorCount: number
totalNextPluginWarningCount: number
} {
let totalNextPluginErrorCount = 0
let totalNextPluginWarningCount = 0
let resultsWithMessages = results.filter(({ messages }) => messages?.length)
// Track number of Next.js plugin errors and warnings
resultsWithMessages.forEach(({ messages }) => {
const res = pluginCount(messages)
totalNextPluginErrorCount += res.nextPluginErrorCount
totalNextPluginWarningCount += res.nextPluginWarningCount
})
// Use user defined formatter or Next.js's built-in custom formatter
const output = format
? format(resultsWithMessages)
: resultsWithMessages
.map(({ messages, filePath }) =>
formatMessage(baseDir, messages, filePath)
)
.join('\n')
return {
output:
resultsWithMessages.length > 0
? output +
`\n\n${chalk.cyan(
'info'
)} - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rules`
: '',
totalNextPluginErrorCount,
totalNextPluginWarningCount,
}
}