lint: replace and add few more rules

This commit is contained in:
Simek
2026-04-30 16:21:11 +02:00
committed by Thibault Duplessis
parent 030acdfe86
commit d6da619d7c
18 changed files with 34 additions and 35 deletions
+5 -2
View File
@@ -50,15 +50,18 @@
"typescript/no-unnecessary-type-arguments": "error",
"typescript/no-unnecessary-type-assertion": "error",
"typescript/no-unnecessary-type-constraint": "error",
"typescript/prefer-find": "error",
"typescript/prefer-includes": "error",
"typescript/prefer-readonly": "error",
"typescript/prefer-reduce-type-parameter": "error",
"typescript/prefer-string-starts-ends-with": "error",
"unicorn/no-immediate-mutation": "error",
"unicorn/no-unnecessary-array-flat-depth": "error",
"unicorn/no-useless-collection-argument": "error",
"unicorn/prefer-array-find": "error",
"unicorn/prefer-array-flat": "error",
"unicorn/prefer-array-flat-map": "error",
"unicorn/prefer-array-some": "error",
"unicorn/prefer-date-now": "error",
"unicorn/prefer-includes": "error",
"unicorn/prefer-keyboard-event-key": "error",
"unicorn/prefer-node-protocol": "error",
"unicorn/require-number-to-fixed-digits-argument": "error",
+1 -1
View File
@@ -118,7 +118,7 @@ async function parsePackage(root: string): Promise<Package> {
const build = pkgInfo.pkg.build;
// 'hash' and 'sync' paths beginning with '/' are repo relative, otherwise they are package relative
const normalize = (file: string) => (file[0] === '/' ? file.slice(1) : join('ui', pkgInfo.name, file));
const normalize = (file: string) => (file.startsWith('/') ? file.slice(1) : join('ui', pkgInfo.name, file));
const normalizeObject = <T extends Record<string, any>>(o: T) =>
Object.fromEntries(Object.entries(o).map(([k, v]) => [k, typeof v === 'string' ? normalize(v) : v]));
+1 -1
View File
@@ -41,7 +41,7 @@ export default class Navigate {
else this.exitVariation();
};
private exitVariation = (): void => {
private readonly exitVariation = (): void => {
if (this.ctrl.onMainline) return;
let found,
path = treePath.root;
+1 -5
View File
@@ -96,11 +96,7 @@ export function make(send: AnalyseSocketSend, ctrl: AnalyseCtrl): Socket {
// ctrl.setOpening(fen, opening);
},
fen(e: GameUpdate) {
if (
ctrl.forecast &&
e.id === ctrl.data.game.id &&
treeOps.last(ctrl.mainline)!.fen.indexOf(e.fen) !== 0
)
if (ctrl.forecast && e.id === ctrl.data.game.id && !treeOps.last(ctrl.mainline)!.fen.startsWith(e.fen))
ctrl.forecast.reloadToLastPly();
},
analysisProgress(data: ServerEvalData) {
+7 -10
View File
@@ -43,16 +43,13 @@ function listenToReload(container: HTMLElement): void {
function replaceMenuItems(container: HTMLElement, items: MenuItem[]): void {
const menu = getMenuFromDataAttr(container);
const newMenuItemsByCategory: Record<string, MenuItem[]> = items.reduce(
(acc, item) => {
if (!acc[item.category ?? '']) {
acc[item.category ?? ''] = [];
}
acc[item.category ?? ''].push(item);
return acc;
},
{} as Record<string, MenuItem[]>,
);
const newMenuItemsByCategory = items.reduce<Record<string, MenuItem[]>>((acc, item) => {
if (!acc[item.category ?? '']) {
acc[item.category ?? ''] = [];
}
acc[item.category ?? ''].push(item);
return acc;
}, {});
for (const [category, items] of Object.entries(newMenuItemsByCategory)) {
const categoryIndex = menu.items.findIndex(item => item.category === category);
+2 -2
View File
@@ -29,8 +29,8 @@ export async function initModule(): Promise<SoundMove> {
site.sound.url(`instrument/${instrument}/${filename}`),
);
const isPawn = (san: string) => san[0] === san[0].toLowerCase();
const isKing = (san: string) => san[0] === 'K';
const isPawn = (san: string) => san.startsWith(san[0].toLowerCase());
const isKing = (san: string) => san.startsWith('K');
const hasCastle = (san: string) => san.startsWith('O-O');
const hasCheck = (san: string) => san.includes('+');
+1 -1
View File
@@ -61,7 +61,7 @@ function execute(e: string | Entry) {
if (!e) return;
if (typeof e !== 'string' && isLink(e)) location.href = e.href;
else if (isUser(e)) location.href = '/@/' + e.name;
else if (e[0] === '/') command(e.replace(/\//g, ''));
else if (e.startsWith('/')) command(e.replace(/\//g, ''));
// 5kr1/p1p2p2/2b2Q2/3q2r1/2p4p/2P4P/P2P1PP1/1R1K3R b - - 1 23
else if (e.match(/^([1-8pnbrqk]+\/){7}.*/i)) location.href = '/analysis/standard/' + e.replace(/ /g, '_');
else if (e.match(/^[a-zA-Z0-9_-]{2,30}$/)) location.href = '/@/' + e;
+4 -1
View File
@@ -165,7 +165,10 @@ function controls(ctrl: EditorCtrl, state: EditorState): VNode {
return h(
'option',
{
attrs: { value: key[0] === 'w' ? 'white' : 'black', selected: key[0] === ctrl.turn[0] },
attrs: {
value: key.startsWith('w') ? 'white' : 'black',
selected: key.startsWith(ctrl.turn[0]),
},
},
i18n.site[key],
);
+1 -1
View File
@@ -11,7 +11,7 @@ export function toLevel(l: LevelPartial, it: number): Level {
return {
id: it + 1,
apples: [],
color: / w /.test(l.fen) ? 'white' : 'black',
color: l.fen.includes(' w ') ? 'white' : 'black',
detectCapture: l.apples ? false : 'unprotected',
...l,
};
+1 -1
View File
@@ -5,7 +5,7 @@ import { normalizeMove } from 'chessops/chess';
import { shuffle } from '@/algo';
export const fixCrazySan = (san: San): San => (san[0] === 'P' ? san.slice(1) : san);
export const fixCrazySan = (san: San): San => (san.startsWith('P') ? san.slice(1) : san);
export const destsToUcis = (destMap: Dests): Uci[] =>
Array.from(destMap).reduce<Uci[]>((acc, [orig, dests]) => acc.concat(dests.map(dest => orig + dest)), []);
+1 -1
View File
@@ -103,7 +103,7 @@ export function almostSanOf(board: Board, uci: string, legalUcis?: Set<Uci> | un
// pawn moves
if (pt === 'p') {
let san: AlmostSan;
if (uci[0] === uci[2]) san = move[1];
if (uci.startsWith(uci[2])) san = move[1];
else san = uci[0] + 'x' + move[1];
if (move[2]) san += '=' + move[2].toUpperCase();
return san;
+2 -2
View File
@@ -14,11 +14,11 @@ export const toFormLines = (form: HTMLFormElement): FormLines =>
.reduce<FormLines>((o, [k, v]) => (typeof v === 'string' ? ((o[k] = v), o) : o), {});
export const toFormObject = (lines: FormLines): FormObject =>
Object.keys(lines).reduce((o, k) => {
Object.keys(lines).reduce<FormObject>((o, k) => {
const i = k.indexOf('[');
const fk = i > 0 ? k.slice(0, i) : k;
return i > 0 ? { ...o, [fk]: [...(o[fk] || []), lines[k]] } : { ...o, [fk]: lines[k] };
}, {} as FormObject);
}, {});
export const makeStore = (storage: LichessStorage): FormStore => ({
get: () => JSON.parse(storage.get() || 'null'),
+1 -1
View File
@@ -228,7 +228,7 @@ export default class PuzzleCtrl implements CevalHandler {
});
};
private googlyEyesAuto = () => {
private readonly googlyEyesAuto = () => {
if (this.isDaily && new Date().getMonth() === 3 && new Date().getDate() === 1) this.googlyEyesStart();
};
+2 -2
View File
@@ -232,7 +232,7 @@ function onSubmit(
ev.preventDefault();
let input = nv.castlingFlavours(($input.val() as string).trim());
if (isShortCommand(input)) input = '/' + input;
if (input[0] === '/') onCommand(ctrl, notify, input.slice(1), style());
if (input.startsWith('/')) onCommand(ctrl, notify, input.slice(1), style());
else {
const uci = nv.inputToMove(input, ctrl.node.fen, ground);
if (uci && typeof uci === 'string') {
@@ -262,7 +262,7 @@ function onCommand(ctrl: PuzzleCtrl, notify: (txt: string) => void, c: string, s
const pieces = ctrl.ground().state.pieces;
if (lowered === 'l' || lowered === 'last') notify($('.lastMove').text());
else if (lowered === 'v') viewOrAdvanceSolution(ctrl, notify);
else if (lowered.charAt(0) === 'b') commands().board.apply(c, pieces, style);
else if (lowered.startsWith('b')) commands().board.apply(c, pieces, style);
else
notify(
commands().piece.apply(c, pieces, style) ||
+1 -1
View File
@@ -209,7 +209,7 @@ export default class RoundController implements MoveRootCtrl {
private readonly isSimulHost = () => this.data.simul && this.data.simul.hostId === this.opts.userId;
private readonly enpassant = (orig: Key, dest: Key): boolean => {
if (orig[0] === dest[0] || this.chessground.state.pieces.get(dest)?.role !== 'pawn') return false;
if (dest.startsWith(orig[0]) || this.chessground.state.pieces.get(dest)?.role !== 'pawn') return false;
const pos = (dest[0] + orig[1]) as Key;
this.chessground.setPieces(new Map([[pos, undefined]]));
return true;
+1 -1
View File
@@ -55,7 +55,7 @@ const renderDrawOffer = () => hl('draw', { attrs: { title: 'Draw offer' } }, '½
const renderMove = (step: Step, curPly: number, orEmpty: boolean, drawOffers: Set<number>) =>
step
? hl(moveTag, { class: { a1t: step.ply === curPly } }, [
step.san[0] === 'P' ? step.san.slice(1) : step.san,
step.san.startsWith('P') ? step.san.slice(1) : step.san,
drawOffers.has(step.ply) ? renderDrawOffer() : undefined,
])
: orEmpty && hl(moveTag, '…');
+1 -1
View File
@@ -313,7 +313,7 @@ class Builder {
? `\n subs: [${e.subs.length > 1 ? '\n ' : ''}${e.subs
.map(s => {
let c = s.cost.toFixed(2);
if (c.slice(-1) === '0') c = c.slice(0, -1);
if (c.endsWith('0')) c = c.slice(0, -1);
return `{ to: '${s.to}', cost: ${c} }`;
})
.join(',\n ')}${e.subs.length > 1 ? ',\n ],' : '],'}`
+1 -1
View File
@@ -429,7 +429,7 @@ export function initModule({
}
if (srole === 'P') {
addToks(udest, uci); // includes en passant
if (uci[0] === uci[2]) {
if (uci.startsWith(uci[2])) {
addToks(`P${udest}`);
} else if (dp) {
addToks(`${usrc}x${udest}`);