chore: Enforce a few house rules via eslint (#2539)
This commit is contained in:
committed by
dermotduffy
parent
5572ec728e
commit
921d45e577
@@ -13,6 +13,39 @@ const compat = new FlatCompat({
|
||||
allConfig: js.configs.all,
|
||||
});
|
||||
|
||||
// Local rule: ban the em-dash character (U+2014) anywhere, including comments and
|
||||
// strings. The codebase uses a colon or a double hyphen `--` instead. The regex uses
|
||||
// the unicode escape so the character never appears literally in this file.
|
||||
const noEmDash = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: { description: 'Disallow the em-dash character; use ":" or "--" instead.' },
|
||||
messages: {
|
||||
emDash: 'Em-dash character is not allowed; use ":" or "--" instead.',
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
||||
return {
|
||||
Program(node) {
|
||||
const text = sourceCode.getText();
|
||||
const re = /\u2014/g;
|
||||
let match;
|
||||
while ((match = re.exec(text)) !== null) {
|
||||
context.report({
|
||||
node,
|
||||
loc: {
|
||||
start: sourceCode.getLocFromIndex(match.index),
|
||||
end: sourceCode.getLocFromIndex(match.index + 1),
|
||||
},
|
||||
messageId: 'emDash',
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
extends: compat.extends('plugin:@typescript-eslint/recommended', 'prettier'),
|
||||
@@ -23,8 +56,56 @@ export default defineConfig([
|
||||
sourceType: 'module',
|
||||
},
|
||||
|
||||
plugins: {
|
||||
local: { rules: { 'no-em-dash': noEmDash } },
|
||||
},
|
||||
|
||||
rules: {
|
||||
curly: 'error',
|
||||
'local/no-em-dash': 'error',
|
||||
'@typescript-eslint/no-explicit-any': 'error',
|
||||
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||
'@typescript-eslint/parameter-properties': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
// Timers must go through the Timer class (src/utils/timer.ts).
|
||||
{
|
||||
files: ['src/**/*.ts'],
|
||||
rules: {
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector:
|
||||
'CallExpression > Identifier.callee[name=/^(setTimeout|setInterval)$/]',
|
||||
message:
|
||||
'Use the Timer class (src/utils/timer.ts) instead of setTimeout/setInterval.',
|
||||
},
|
||||
{
|
||||
selector: 'MemberExpression[property.name=/^(setTimeout|setInterval)$/]',
|
||||
message:
|
||||
'Use the Timer class (src/utils/timer.ts) instead of window.setTimeout/setInterval.',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// A fire-and-forget promise must be marked with `void` to show it is deliberate.
|
||||
// To know which calls return a promise, this rule needs type information, so the
|
||||
// `project` option below runs the TypeScript type-checker over source while linting.
|
||||
// That makes linting source slower. Tests are excluded: they leave promises unawaited
|
||||
// freely.
|
||||
{
|
||||
files: ['src/**/*.ts'],
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user