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