Skip to content

Commit 00c8e28

Browse files
committed
Convert to new flat config for eslint
1 parent ec25f52 commit 00c8e28

File tree

5 files changed

+55
-52
lines changed

5 files changed

+55
-52
lines changed

bin/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const error =
5454
cli.flagOn.trim && !trim ? 'Value of "trim" must be a positive whole number.' :
5555
null;
5656
if (error)
57-
throw Error('[w3c-html-validator] ' + error);
57+
throw new Error('[w3c-html-validator] ' + error);
5858
if (dryRunMode)
5959
w3cHtmlValidator.dryRunNotice();
6060
if (filenames.length > 1 && !cli.flagOn.quiet)

eslint.config.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// @ts-check
2+
3+
import eslint from '@eslint/js';
4+
import tseslint from 'typescript-eslint';
5+
6+
export default [
7+
eslint.configs.recommended,
8+
...tseslint.configs.strictTypeChecked,
9+
{ ignores: ['**/*.js'] },
10+
{
11+
languageOptions: { parserOptions: { projectService: true } },
12+
rules: {
13+
'@typescript-eslint/no-confusing-void-expression': 'off', //prefer minimal arrow functions
14+
'@typescript-eslint/no-floating-promises': 'off', //annimations may be fire-and-forget
15+
'@typescript-eslint/no-misused-promises': 'off', //annimations may be fire-and-forget
16+
'@typescript-eslint/no-non-null-assertion': 'off', //ts cannot always know value exists
17+
'@typescript-eslint/restrict-template-expressions': 'off', //numbers in templates are natural
18+
'@typescript-eslint/unbound-method': 'off', //safer to not use 'this'
19+
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'off', //clarity over theoretical exceptions
20+
},
21+
},
22+
];

package.json

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,13 @@
3838
"node": true,
3939
"mocha": true
4040
},
41-
"eslintConfig": {
42-
"ignorePatterns": [
43-
"build",
44-
"dist",
45-
"node_modules"
46-
],
47-
"root": true,
48-
"parser": "@typescript-eslint/parser",
49-
"plugins": [
50-
"@typescript-eslint"
51-
],
52-
"extends": [
53-
"eslint:recommended",
54-
"plugin:@typescript-eslint/recommended"
55-
],
56-
"rules": {
57-
"@typescript-eslint/no-non-null-assertion": "off"
58-
}
59-
},
6041
"runScriptsConfig": {
6142
"clean": [
6243
"rimraf build dist"
6344
],
6445
"lint": [
6546
"jshint . --exclude-path .gitignore",
66-
"eslint --max-warnings 0 . --ext .ts"
47+
"eslint --max-warnings 0"
6748
],
6849
"build": [
6950
"tsc",
@@ -79,26 +60,26 @@
7960
"chalk": "~5.3",
8061
"cli-argv-util": "~1.2",
8162
"fancy-log": "~2.0",
82-
"glob": "~10.4",
63+
"glob": "~11.0",
8364
"slash": "~5.1",
8465
"superagent": "~9.0"
8566
},
8667
"devDependencies": {
87-
"@eslint/js": "~9.3",
68+
"@eslint/js": "~9.9",
8869
"@types/fancy-log": "~2.0",
89-
"@types/node": "~20.12",
70+
"@types/node": "~22.2",
9071
"@types/superagent": "~8.1",
9172
"add-dist-header": "~1.4",
9273
"assert-deep-strict-equal": "~1.2",
9374
"copy-file-util": "~1.2",
9475
"copy-folder-util": "~1.1",
95-
"eslint": "8.57.0",
76+
"eslint": "~9.9",
9677
"jshint": "~2.13",
9778
"merge-stream": "~2.0",
98-
"mocha": "~10.4",
99-
"rimraf": "~5.0",
100-
"run-scripts-util": "~1.2",
101-
"typescript": "~5.4",
102-
"typescript-eslint": "~7.11"
79+
"mocha": "~10.7",
80+
"rimraf": "~6.0",
81+
"run-scripts-util": "~1.3",
82+
"typescript": "~5.5",
83+
"typescript-eslint": "~8.0"
10384
}
10485
}

tsconfig.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,21 @@
33
"target": "ES2021",
44
"module": "ES2020",
55
"moduleResolution": "node",
6+
"esModuleInterop": true,
67
"declaration": true,
78
"outDir": "build",
89
"newLine": "lf",
10+
"removeComments": true,
911
"strict": true,
1012
"allowSyntheticDefaultImports": true,
1113
"alwaysStrict": true,
12-
"esModuleInterop": true,
1314
"exactOptionalPropertyTypes": true,
1415
"forceConsistentCasingInFileNames": true,
1516
"noFallthroughCasesInSwitch": true,
1617
"noImplicitAny": true,
1718
"noImplicitReturns": true,
1819
"noImplicitThis": true,
1920
"noUncheckedIndexedAccess": true,
20-
"noUnusedLocals": true,
21-
"removeComments": true
21+
"noUnusedLocals": true
2222
}
2323
}

w3c-html-validator.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// W3C HTML Validator ~ MIT License
22

33
// Imports
4-
import chalk from 'chalk';
4+
import chalk, { ChalkInstance } from 'chalk';
55
import fs from 'fs';
66
import log from 'fancy-log';
77
import request from 'superagent';
@@ -28,7 +28,7 @@ export type ValidatorResultsMessage = {
2828
type: 'info' | 'error' | 'non-document-error' | 'network-error',
2929
subType?: 'warning' | 'fatal' | 'io' | 'schema' | 'internal',
3030
message: string, //example: 'Section lacks heading.'
31-
extract: string, //example: '<section>Hi</section>'
31+
extract?: string, //example: '<section>Hi</section>'
3232
lastLine: number,
3333
firstColumn: number,
3434
lastColumn: number,
@@ -73,11 +73,11 @@ const w3cHtmlValidator = {
7373
};
7474
const settings = { ...defaults, ...options };
7575
if (!settings.html && !settings.filename && !settings.website)
76-
throw Error('[w3c-html-validator] Must specify the "html", "filename", or "website" option.');
76+
throw new Error('[w3c-html-validator] Must specify the "html", "filename", or "website" option.');
7777
if (![null, 'info', 'warning'].includes(settings.ignoreLevel))
78-
throw Error('[w3c-html-validator] Invalid ignoreLevel option: ' + settings.ignoreLevel);
78+
throw new Error(`[w3c-html-validator] Invalid ignoreLevel option: ${settings.ignoreLevel}`);
7979
if (settings.output !== 'json' && settings.output !== 'html')
80-
throw Error('[w3c-html-validator] Option "output" must be "json" or "html".');
80+
throw new Error('[w3c-html-validator] Option "output" must be "json" or "html".');
8181
const filename = settings.filename ? slash(settings.filename) : null;
8282
const mode = settings.html ? 'html' : filename ? 'filename' : 'website';
8383
const readFile = (filename: string) => fs.readFileSync(filename, 'utf-8').replace(/\r/g, '');
@@ -93,7 +93,7 @@ const w3cHtmlValidator = {
9393
const json = settings.output === 'json';
9494
const success = '<p class="success">';
9595
const titleLookup = {
96-
html: 'HTML String (characters: ' + inputHtml?.length + ')',
96+
html: `HTML String (characters: ${inputHtml?.length})`,
9797
filename: filename,
9898
website: settings.website,
9999
};
@@ -108,28 +108,28 @@ const w3cHtmlValidator = {
108108
const isImportant = (message: ValidatorResultsMessage): boolean =>
109109
aboveIgnoreLevel(message) && !matchesSkipPattern(message.message);
110110
if (json)
111-
response.body.messages = response.body.messages?.filter(isImportant) ?? [];
111+
response.body.messages = response.body.messages?.filter(isImportant) ?? []; //eslint-disable-line
112112
return response;
113113
};
114114
const toValidatorResults = (response: request.Response): ValidatorResults => ({
115-
validates: json ? !response.body.messages.length : !!response.text?.includes(success),
115+
validates: json ? !response.body.messages.length : !!response.text?.includes(success), //eslint-disable-line
116116
mode: mode,
117117
title: <string>titleLookup[mode],
118118
html: inputHtml,
119119
filename: filename,
120120
website: settings.website || null,
121121
output: <ValidatorResultsOutput>settings.output,
122122
status: response.statusCode || -1,
123-
messages: json ? response.body.messages : null,
123+
messages: json ? response.body.messages : null, //eslint-disable-line
124124
display: json ? null : response.text,
125125
dryRun: settings.dryRun,
126126
});
127127
type ReasonResponse = { request: { url: string }, res: { statusMessage: string }};
128128
type ReasonError = Error & { errno: number, response: request.Response & ReasonResponse };
129129
const handleError = (reason: ReasonError): ValidatorResults => {
130-
const errRes = reason.response ?? <ReasonError['response']>{};
130+
const errRes = reason.response ?? <ReasonError['response']>{}; //eslint-disable-line
131131
const getMsg = () => [errRes.status, errRes.res.statusMessage, errRes.request.url];
132-
const message = reason.response ? getMsg() : [reason.errno, reason.message];
132+
const message = reason.response ? getMsg() : [reason.errno, reason.message]; //eslint-disable-line
133133
errRes.body = { messages: [{ type: 'network-error', message: message.join(' ') }] };
134134
return toValidatorResults(errRes);
135135
};
@@ -150,7 +150,7 @@ const w3cHtmlValidator = {
150150
},
151151

152152
summary(numFiles: number) {
153-
log(chalk.gray('w3c-html-validator'), chalk.magenta('files: ' + numFiles));
153+
log(chalk.gray('w3c-html-validator'), chalk.magenta('files: ' + String(numFiles)));
154154
},
155155

156156
reporter(results: ValidatorResults, options?: Partial<ReporterSettings>): ValidatorResults {
@@ -161,21 +161,21 @@ const w3cHtmlValidator = {
161161
title: null,
162162
};
163163
const settings = { ...defaults, ...options };
164-
if (typeof results?.validates !== 'boolean')
165-
throw Error('[w3c-html-validator] Invalid results for reporter(): ' + String(results));
164+
if (typeof results?.validates !== 'boolean') //eslint-disable-line
165+
throw new Error('[w3c-html-validator] Invalid results for reporter(): ' + String(results));
166166
const messages = results.messages ?? [];
167167
const title = settings.title ?? results.title;
168168
const status = results.validates ? chalk.green.bold('✔ pass') : chalk.red.bold('✘ fail');
169-
const count = results.validates ? '' : '(messages: ' + messages!.length + ')';
169+
const count = results.validates ? '' : `(messages: ${messages.length})`;
170170
if (!results.validates || !settings.quiet)
171171
log(chalk.gray('w3c-html-validator'), status, chalk.blue.bold(title), chalk.white(count));
172-
const typeColorMap = {
172+
const typeColorMap = <{ [messageType: string]: ChalkInstance }>{
173173
error: chalk.red.bold,
174174
warning: chalk.yellow.bold,
175175
info: chalk.white.bold,
176176
};
177177
const logMessage = (message: ValidatorResultsMessage) => {
178-
const type = <keyof typeof typeColorMap>(message.subType ?? message.type);
178+
const type = message.subType ?? message.type;
179179
const typeColor = typeColorMap[type] ?? chalk.redBright.bold;
180180
const location = `line ${message.lastLine}, column ${message.firstColumn}:`;
181181
const lineText = message.extract?.replace(/\n/g, '\\n');
@@ -190,11 +190,11 @@ const w3cHtmlValidator = {
190190
const toString = (message: ValidatorResultsMessage) =>
191191
`${message.subType ?? message.type} line ${message.lastLine} column ${message.firstColumn}`;
192192
const fileDetails = () =>
193-
results.filename + ' -- ' + results.messages!.map(toString).join(', ');
193+
`${results.filename} -- ${results.messages!.map(toString).join(', ')}`;
194194
return !results.filename ? results.messages![0]!.message : fileDetails();
195195
};
196196
if (!settings.continueOnFail && !results.validates)
197-
throw Error('[w3c-html-validator] Failed: ' + failDetails());
197+
throw new Error('[w3c-html-validator] Failed: ' + failDetails());
198198
return results;
199199
},
200200

0 commit comments

Comments
 (0)