Skip to content

Commit

Permalink
Require Node.js 18
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Oct 28, 2023
1 parent 7289acd commit 13383af
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 162 deletions.
31 changes: 8 additions & 23 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,20 @@
import type {ESLint, Linter} from 'eslint';

export = formatterPretty;

/**
Pretty formatter for [ESLint](https://eslint.org).
@param results - Lint result for the individual files.
@param data - Extended information related to the analysis results.
@returns The formatted output.
*/
declare function formatterPretty(
results: readonly formatterPretty.LintResult[],
data?: ESLint.LintResultData
export default function eslintFormatterPretty(
results: LintResult[],
data?: LintResultData
): string;

declare namespace formatterPretty {
interface LintResult {
readonly filePath: string;
readonly errorCount: number;
readonly warningCount: number;
readonly messages: readonly LintMessage[];
}

type Severity = Linter.Severity | 'warning' | 'error';
export type LintResult = ESLint.LintResult;
export type LintResultData = ESLint.LintResultData;
export type Severity = Linter.Severity;
export type LintMessage = Linter.LintMessage;

interface LintMessage {
readonly severity: Severity;
readonly fatal?: boolean;
readonly line?: number;
readonly column?: number;
readonly message: string;
readonly ruleId?: string | null;
}
}
export {Linter} from 'eslint';
150 changes: 74 additions & 76 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
'use strict';
const path = require('path');
const chalk = require('chalk');
const logSymbols = require('log-symbols');
const plur = require('plur');
const stringWidth = require('string-width');
const ansiEscapes = require('ansi-escapes');
const {supportsHyperlink} = require('supports-hyperlinks');
const getRuleDocs = require('eslint-rule-docs');

module.exports = (results, data) => {
import process from 'node:process';
import path from 'node:path';
import chalk from 'chalk';
import logSymbols from 'log-symbols';
import plur from 'plur';
import stringWidth from 'string-width';
import ansiEscapes from 'ansi-escapes';
import {supportsHyperlink} from 'supports-hyperlinks';
import getRuleDocs from 'eslint-rule-docs';

export default function eslintFormatterPretty(results, data) {
const lines = [];
let errorCount = 0;
let warningCount = 0;
Expand All @@ -17,7 +17,7 @@ module.exports = (results, data) => {
let maxMessageWidth = 0;
let showLineNumbers = false;

results
for (const result of results
.sort((a, b) => {
if (a.errorCount === b.errorCount) {
return b.warningCount - a.warningCount;
Expand All @@ -32,76 +32,74 @@ module.exports = (results, data) => {
}

return b.errorCount - a.errorCount;
})
.forEach(result => {
const {messages, filePath} = result;
})) {
const {messages, filePath} = result;

if (messages.length === 0) {
return;
}
if (messages.length === 0) {
continue;
}

errorCount += result.errorCount;
warningCount += result.warningCount;
errorCount += result.errorCount;
warningCount += result.warningCount;

if (lines.length !== 0) {
lines.push({type: 'separator'});
}

const firstErrorOrWarning = messages.find(({severity}) => severity === 2) || messages[0];
if (lines.length > 0) {
lines.push({type: 'separator'});
}

lines.push({
type: 'header',
filePath,
relativeFilePath: path.relative('.', filePath),
firstLineCol: firstErrorOrWarning.line + ':' + firstErrorOrWarning.column
});
const firstErrorOrWarning = messages.find(({severity}) => severity === 2) ?? messages[0];

messages
.sort((a, b) => {
if (a.fatal === b.fatal && a.severity === b.severity) {
if (a.line === b.line) {
return a.column < b.column ? -1 : 1;
}
lines.push({
type: 'header',
filePath,
relativeFilePath: path.relative('.', filePath),
firstLineCol: firstErrorOrWarning.line + ':' + firstErrorOrWarning.column,
});

return a.line < b.line ? -1 : 1;
for (const x of messages
.sort((a, b) => {
if (a.fatal === b.fatal && a.severity === b.severity) {
if (a.line === b.line) {
return a.column < b.column ? -1 : 1;
}

if ((a.fatal || a.severity === 2) && (!b.fatal || b.severity !== 2)) {
return 1;
}
return a.line < b.line ? -1 : 1;
}

return -1;
})
.forEach(x => {
let {message} = x;

// Stylize inline code blocks
message = message.replace(/\B`(.*?)`\B|\B'(.*?)'\B/g, (m, p1, p2) => chalk.bold(p1 || p2));

const line = String(x.line || 0);
const column = String(x.column || 0);
const lineWidth = stringWidth(line);
const columnWidth = stringWidth(column);
const messageWidth = stringWidth(message);

maxLineWidth = Math.max(lineWidth, maxLineWidth);
maxColumnWidth = Math.max(columnWidth, maxColumnWidth);
maxMessageWidth = Math.max(messageWidth, maxMessageWidth);
showLineNumbers = showLineNumbers || x.line || x.column;

lines.push({
type: 'message',
severity: (x.fatal || x.severity === 2 || x.severity === 'error') ? 'error' : 'warning',
line,
lineWidth,
column,
columnWidth,
message,
messageWidth,
ruleId: x.ruleId || ''
});
});
});
if ((a.fatal || a.severity === 2) && (!b.fatal || b.severity !== 2)) {
return 1;
}

return -1;
})) {
let {message} = x;

// Stylize inline code blocks
message = message.replaceAll(/\B`(.*?)`\B|\B'(.*?)'\B/g, (m, p1, p2) => chalk.bold(p1 ?? p2));

const line = String(x.line ?? 0);
const column = String(x.column ?? 0);
const lineWidth = stringWidth(line);
const columnWidth = stringWidth(column);
const messageWidth = stringWidth(message);

maxLineWidth = Math.max(lineWidth, maxLineWidth);
maxColumnWidth = Math.max(columnWidth, maxColumnWidth);
maxMessageWidth = Math.max(messageWidth, maxMessageWidth);
showLineNumbers = showLineNumbers || x.line || x.column;

lines.push({
type: 'message',
severity: (x.fatal || x.severity === 2 || x.severity === 'error') ? 'error' : 'warning',
line,
lineWidth,
column,
columnWidth,
message,
messageWidth,
ruleId: x.ruleId ?? '',
});
}
}

let output = '\n';

Expand Down Expand Up @@ -135,8 +133,8 @@ module.exports = (results, data) => {
x.severity === 'warning' ? logSymbols.warning : logSymbols.error,
' '.repeat(maxLineWidth - x.lineWidth) + chalk.dim(x.line + chalk.gray(':') + x.column),
' '.repeat(maxColumnWidth - x.columnWidth) + x.message,
' '.repeat(maxMessageWidth - x.messageWidth) +
(ruleUrl && supportsHyperlink(process.stdout) ? ansiEscapes.link(chalk.dim(x.ruleId), ruleUrl) : chalk.dim(x.ruleId))
' '.repeat(maxMessageWidth - x.messageWidth)
+ (ruleUrl && supportsHyperlink(process.stdout) ? ansiEscapes.link(chalk.dim(x.ruleId), ruleUrl) : chalk.dim(x.ruleId)),
];

if (!showLineNumbers) {
Expand All @@ -158,4 +156,4 @@ module.exports = (results, data) => {
}

return (errorCount + warningCount) > 0 ? output : '';
};
}
62 changes: 31 additions & 31 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
import type {ESLint} from 'eslint';
import {expectType} from 'tsd';
import formatterPretty = require('.');

// Test type exports
type LintResult = formatterPretty.LintResult;
type LintMessage = formatterPretty.LintMessage;
type Severity = formatterPretty.Severity;
import eslintFormatterPretty, {
type LintResult,
type LintMessage,
type Severity,
} from './index.js';

// Test LintResult interface members
declare const lintResult: LintResult;
expectType<string>(lintResult.filePath);
expectType<number>(lintResult.errorCount);
expectType<number>(lintResult.warningCount);
expectType<readonly LintMessage[]>(lintResult.messages);
expectType<LintMessage[]>(lintResult.messages);

// Test LintMessage interface members
const lintMessage = lintResult.messages[0];
expectType<Severity>(lintMessage.severity);
expectType<string>(lintMessage.message);
expectType<boolean | undefined>(lintMessage.fatal);
expectType<number | undefined>(lintMessage.line);
expectType<number | undefined>(lintMessage.column);
expectType<string | null | undefined>(lintMessage.ruleId);
expectType<true | undefined>(lintMessage.fatal);
expectType<number>(lintMessage.line);
expectType<number>(lintMessage.column);
expectType<string | null >(lintMessage.ruleId); // eslint-disable-line @typescript-eslint/ban-types

// Test formatterPretty()
declare const lintResults: LintResult[];
declare const eslintLintResults: ESLint.LintResult[];
declare const lintResultData: ESLint.LintResultData;

expectType<string>(formatterPretty(lintResults));
expectType<string>(formatterPretty(eslintLintResults));
expectType<string>(formatterPretty(eslintLintResults, lintResultData));

interface PartialLintResult {
filePath: string;
errorCount: number;
warningCount: number;
messages: Array<{
fileName: string;
message: string;
severity: 'error' | 'warning';
line?: number;
column?: number;
}>;
}

declare const partialLintResults: PartialLintResult[];

expectType<string>(formatterPretty(partialLintResults));
expectType<string>(eslintFormatterPretty(lintResults));
expectType<string>(eslintFormatterPretty(eslintLintResults));
expectType<string>(eslintFormatterPretty(eslintLintResults, lintResultData));

// FIXME
// type PartialLintResult = {
// filePath: string;
// errorCount: number;
// warningCount: number;
// messages: Array<{
// fileName: string;
// message: string;
// severity: 0 | 1 | 2;
// line?: number;
// column?: number;
// }>;
// };

// declare const partialLintResults: PartialLintResult[];

// expectType<string>(eslintFormatterPretty(partialLintResults));
36 changes: 23 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
"email": "[email protected]",
"url": "https://sindresorhus.com"
},
"type": "module",
"exports": {
"types": "./index.d.ts",
"default": "./index.js"
},
"engines": {
"node": ">=14.16"
"node": ">=18"
},
"scripts": {
"test": "xo && ava && tsd"
Expand All @@ -29,23 +34,28 @@
"validate"
],
"dependencies": {
"@types/eslint": "^8.0.0",
"ansi-escapes": "^4.2.1",
"chalk": "^4.1.0",
"@types/eslint": "^8.44.6",
"ansi-escapes": "^6.2.0",
"chalk": "^5.3.0",
"eslint-rule-docs": "^1.1.235",
"log-symbols": "^4.0.0",
"plur": "^4.0.0",
"string-width": "^4.2.0",
"supports-hyperlinks": "^2.0.0"
"log-symbols": "^6.0.0",
"plur": "^5.1.0",
"string-width": "^7.0.0",
"supports-hyperlinks": "^3.0.0"
},
"devDependencies": {
"ava": "^2.4.0",
"strip-ansi": "^6.0.0",
"tsd": "^0.17.0",
"typescript": "^4.3.2",
"xo": "^0.32.0"
"ava": "^5.3.1",
"strip-ansi": "^7.1.0",
"tsd": "^0.29.0",
"typescript": "^5.2.2",
"xo": "^0.56.0"
},
"ava": {
"serial": true
},
"xo": {
"rules": {
"import/no-extraneous-dependencies": "off"
}
}
}
Loading

0 comments on commit 13383af

Please sign in to comment.