v0.5.2 — Add ESLint + typescript-eslint, fix lint errors
Add flat-config ESLint with typescript-eslint recommended rules, fix all lint errors (unused imports/vars, empty catches, Function types, prefer-const, useless assignments), and rename stale kpc- CSS class to kcc-. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import eslint from "@eslint/js";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default tseslint.config(
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
{
|
||||
ignores: ["dist/", "out/", "scripts/"],
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
Generated
+911
-25
File diff suppressed because it is too large
Load Diff
+6
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "krunker-civilian-client",
|
||||
"version": "0.5.1",
|
||||
"version": "0.5.2",
|
||||
"description": "Cross-platform Krunker game client",
|
||||
"main": "dist/main/index.js",
|
||||
"homepage": "https://gitea.crjlab.net/bigjakk/krunker-civilian-client",
|
||||
@@ -17,18 +17,22 @@
|
||||
"dist:win": "npm run build && electron-builder --win",
|
||||
"dist:linux": "npm run build && electron-builder --linux",
|
||||
"dist:all": "npm run build && electron-builder --win --linux",
|
||||
"clean": "rimraf dist out"
|
||||
"clean": "rimraf dist out",
|
||||
"lint": "eslint src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"electron-store": "^8.2.0",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@types/node": "^22.0.0",
|
||||
"electron": "npm:electron-nightly@42.0.0-nightly.20260227",
|
||||
"electron-builder": "^26.0.0",
|
||||
"eslint": "^10.0.2",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.7.0",
|
||||
"typescript-eslint": "^8.56.1",
|
||||
"vite": "^6.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,7 +518,7 @@ export const MATCHMAKER_SETTINGS_CSS = `
|
||||
`;
|
||||
|
||||
export const TRANSLATOR_CSS = `
|
||||
.kpc-translation {
|
||||
.kcc-translation {
|
||||
color: #88ff88;
|
||||
font-style: italic;
|
||||
margin-left: 8px;
|
||||
|
||||
+4
-5
@@ -1,4 +1,4 @@
|
||||
import { app, BrowserWindow, Menu, clipboard, dialog, ipcMain, protocol, safeStorage, session, shell } from 'electron';
|
||||
import { app, BrowserWindow, Menu, clipboard, dialog, ipcMain, safeStorage, session, shell } from 'electron';
|
||||
import { join } from 'path';
|
||||
import { existsSync, mkdirSync, promises as fsp } from 'fs';
|
||||
import { get as httpsGet } from 'https';
|
||||
@@ -14,6 +14,7 @@ import { showUpdateWindow } from './update-window';
|
||||
import { DiscordRPC } from './discord-rpc';
|
||||
|
||||
// ── App version for API calls ──
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const appVersion: string = require('../../package.json').version;
|
||||
|
||||
// ── Region ping cache ──
|
||||
@@ -247,7 +248,7 @@ async function launchApp(): Promise<void> {
|
||||
try {
|
||||
const host = new URL(details.url).hostname;
|
||||
if (host.endsWith('krunker.io')) return callback({});
|
||||
} catch {}
|
||||
} catch { /* ignore invalid URLs */ }
|
||||
// Otherwise it matched an ad-block pattern — cancel it
|
||||
callback({ cancel: true });
|
||||
});
|
||||
@@ -317,8 +318,6 @@ async function launchApp(): Promise<void> {
|
||||
}
|
||||
|
||||
// ── Common output directory (used by folder actions) ──
|
||||
const outputDir = join(app.getPath('documents'), 'Krunker Civilian Client');
|
||||
|
||||
// ── Configurable keybinds via before-input-event ──
|
||||
win.webContents.on('before-input-event', (event, input) => {
|
||||
if (input.type !== 'keyDown') return;
|
||||
@@ -333,7 +332,7 @@ async function launchApp(): Promise<void> {
|
||||
event.preventDefault();
|
||||
} else if (matchesKeybind(input, binds.joinFromClipboard)) {
|
||||
const text = clipboard.readText();
|
||||
try { const u = new URL(text); if (u.protocol === 'https:' && u.hostname.endsWith('krunker.io')) win.loadURL(text); } catch {};
|
||||
try { const u = new URL(text); if (u.protocol === 'https:' && u.hostname.endsWith('krunker.io')) win.loadURL(text); } catch { /* ignore invalid URLs */ }
|
||||
event.preventDefault();
|
||||
} else if (matchesKeybind(input, binds.copyGameLink)) {
|
||||
clipboard.writeText(win.webContents.getURL());
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@ function makeLogger(getStream: () => WriteStream) {
|
||||
|
||||
export const electronLog = makeLogger(() => electronStream);
|
||||
|
||||
export function getLogPath(type: 'electron'): string {
|
||||
export function getLogPath(_type: 'electron'): string {
|
||||
init();
|
||||
return electronPath;
|
||||
}
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ export class ResourceSwapper {
|
||||
this.swapFiles.set(name, join(this.swapDir, name));
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
} catch {
|
||||
console.error(`Failed to scan swap directory prefix: ${prefix}`);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { get as httpsGet, request as httpsRequest } from 'https';
|
||||
import { get as httpsGet } from 'https';
|
||||
import { createWriteStream, renameSync, unlinkSync, existsSync } from 'fs';
|
||||
import { spawn } from 'child_process';
|
||||
import { app } from 'electron';
|
||||
|
||||
@@ -49,7 +49,7 @@ export class UserscriptManager {
|
||||
|
||||
/** Load tracker.json, add new scripts as disabled, prune deleted scripts */
|
||||
async loadTracker(scripts: ScriptFile[]): Promise<ScriptTracker> {
|
||||
let tracker: ScriptTracker = {};
|
||||
let tracker: ScriptTracker;
|
||||
try {
|
||||
tracker = JSON.parse(await fsp.readFile(this.trackerPath, 'utf-8'));
|
||||
} catch { tracker = {}; }
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ipcRenderer } from 'electron';
|
||||
import { fetchGame, MATCHMAKER_GAMEMODES, MATCHMAKER_REGIONS, MATCHMAKER_REGION_NAMES } from './matchmaker';
|
||||
import type { MatchmakerConfig } from './matchmaker';
|
||||
import { initUserscripts, getInstances, setScriptEnabled } from './userscripts';
|
||||
import type { UserscriptInstance, UserscriptSetting } from './userscripts';
|
||||
import type { UserscriptInstance } from './userscripts';
|
||||
import { initTranslator, updateTranslatorConfig } from './translator';
|
||||
import { setDeathAnimBlock, escapeHtml } from './utils';
|
||||
import type { Keybind } from '../main/config';
|
||||
@@ -10,7 +10,7 @@ import type { Keybind } from '../main/config';
|
||||
|
||||
// ── Save console methods before Krunker overwrites them ──
|
||||
// Wrapped to forward errors/warnings always, and logs when verbose is enabled
|
||||
let _verboseLogging = false;
|
||||
const _verboseLogging = false;
|
||||
|
||||
const _console = {
|
||||
log: (...args: unknown[]) => {
|
||||
@@ -75,7 +75,7 @@ function updateRefreshNotification(): void {
|
||||
if (refreshPopupEl) { refreshPopupEl.remove(); refreshPopupEl = null; }
|
||||
return;
|
||||
}
|
||||
if (refreshPopupEl) { try { refreshPopupEl.remove(); } catch (_e) { /* noop */ } }
|
||||
if (refreshPopupEl) { try { refreshPopupEl.remove(); } catch { /* noop */ } }
|
||||
refreshPopupEl = document.createElement('div');
|
||||
refreshPopupEl.className = 'kpc-holder-update refresh-popup';
|
||||
if (refreshLevel === RefreshLevel.restart) {
|
||||
@@ -1115,7 +1115,7 @@ function renderUserscriptsSection(body: HTMLElement): void {
|
||||
scriptRow.className = 'setting settName safety-0 bool';
|
||||
|
||||
const displayName = escapeHtml(inst.meta.name || inst.filename);
|
||||
let metaParts: string[] = [];
|
||||
const metaParts: string[] = [];
|
||||
if (inst.meta.author) metaParts.push('by ' + escapeHtml(inst.meta.author));
|
||||
if (inst.meta.version) metaParts.push('v' + escapeHtml(inst.meta.version));
|
||||
const metaLine = metaParts.length > 0 ? '<span class="kpc-us-meta">' + metaParts.join(' · ') + '</span>' : '';
|
||||
@@ -1352,7 +1352,7 @@ ipcRenderer.on('main_did-finish-load', () => {
|
||||
Promise.all([
|
||||
ipcRenderer.invoke('get-all-config', ['ui', 'userscripts', 'game', 'translator', 'keybinds', 'discord']),
|
||||
ipcRenderer.invoke('get-platform'),
|
||||
]).then(([allConf, platformInfo]: [any, any]) => {
|
||||
]).then(([allConf, _platformInfo]: [any, any]) => {
|
||||
const uiConf = allConf.ui;
|
||||
const usConf = allConf.userscripts;
|
||||
const gameConf = allConf.game;
|
||||
@@ -1417,7 +1417,7 @@ ipcRenderer.on('main_did-finish-load', () => {
|
||||
let gameStartTimestamp = Math.floor(Date.now() / 1000);
|
||||
|
||||
function pollDiscordState(): void {
|
||||
let details = '';
|
||||
let details: string;
|
||||
let state = '';
|
||||
let startTimestamp: number | undefined = undefined;
|
||||
|
||||
@@ -1426,7 +1426,7 @@ ipcRenderer.on('main_did-finish-load', () => {
|
||||
|
||||
let gameActivity: any = null;
|
||||
if (typeof w.getGameActivity === 'function') {
|
||||
try { gameActivity = w.getGameActivity(); } catch {}
|
||||
try { gameActivity = w.getGameActivity(); } catch { /* game API unavailable */ }
|
||||
}
|
||||
|
||||
if (spectating) {
|
||||
|
||||
@@ -138,6 +138,7 @@ const SYSTEM_PATTERNS = [
|
||||
// ── Pre-translation filtering ──
|
||||
|
||||
function isLatinOnly(text: string): boolean {
|
||||
// eslint-disable-next-line no-control-regex
|
||||
return /^[\x00-\x7F\u00C0-\u024F\u1E00-\u1EFF\s\d.,!?;:'"()\-/@#$%^&*+=~`[\]{}|\\<>]+$/u.test(text);
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ function toggleCSS(css: string, identifier: string, value: boolean): void {
|
||||
|
||||
function executeScript(
|
||||
instance: UserscriptInstance,
|
||||
_console: { log: Function; warn: Function; error: Function },
|
||||
_console: { log: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void },
|
||||
): void {
|
||||
if (instance.executed) return;
|
||||
|
||||
@@ -164,7 +164,7 @@ export function getInstances(): UserscriptInstance[] {
|
||||
}
|
||||
|
||||
export async function initUserscripts(
|
||||
_console: { log: Function; warn: Function; error: Function },
|
||||
_console: { log: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void },
|
||||
): Promise<void> {
|
||||
const { scripts, tracker } = await ipcRenderer.invoke('userscripts-scan');
|
||||
if (!scripts || scripts.length === 0) {
|
||||
@@ -219,7 +219,7 @@ export async function initUserscripts(
|
||||
export function setScriptEnabled(
|
||||
filename: string,
|
||||
enabled: boolean,
|
||||
_console: { log: Function; warn: Function; error: Function },
|
||||
_console: { log: (...args: unknown[]) => void; warn: (...args: unknown[]) => void; error: (...args: unknown[]) => void },
|
||||
): { needsReload: boolean } {
|
||||
const inst = instances.find(i => i.filename === filename);
|
||||
if (!inst) return { needsReload: false };
|
||||
|
||||
Reference in New Issue
Block a user