From 47e7924a49ae5156818483e8ecf0630e4f04e9fb Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 25 May 2026 00:55:16 +0200 Subject: [PATCH] Fix all ESLint errors across project --- AGENTS.md | 2 ++ README.md | 4 ++-- app.js | 33 ++++++++++----------------------- build-less.js | 1 + eslint.config.mjs | 4 ++-- pgn-parser.js | 5 +++++ style.css | 4 ++++ style.less | 5 +++++ 8 files changed, 31 insertions(+), 27 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index de8047d..5f4992b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,3 +3,5 @@ - Nach jeder Änderung am Proxy (server.py) oder an den Requests (app.js) muss der Proxy neu gestartet werden: erst alten Prozess killen (`Get-Process -Name python | Stop-Process -Force`), dann unsichtbar starten. - Commits und Push erfolgen nur durch expliziten Befehl des Nutzers. - Der Server (server.py) wird immer unsichtbar gestartet: `Start-Process -NoNewWindow -FilePath "python" -ArgumentList "server.py"` +- **LESS-Workflow**: CSS-Quelldatei ist `style.less`. Bei Serverstart wird automatisch `style.css` via `node build-less.js` kompiliert. Bei manuellen Änderungen an `style.less`: `node build-less.js` ausführen, dann Server neustarten. +- `style.css` ist auto-generiert – keine manuellen Änderungen dort vornehmen. diff --git a/README.md b/README.md index ec4c347..63baebe 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Live-Überwachung von Lara Kiesewetters Partien bei der **ODJM (Offene Deutsche ## Projektstruktur -``` +```text ├── app.js # Hauptlogik (Brett, UI, Auto-Refresh) ├── index.html # HTML-Grundgerüst ├── style.css # Dark-Theme-Styling @@ -42,7 +42,7 @@ Live-Überwachung von Lara Kiesewetters Partien bei der **ODJM (Offene Deutsche Der Server läuft auf `http://localhost:8111`. 2. **Öffne die App im Browser:** - ``` + ```text http://localhost:8111 ``` (Der Server serviert auch die statischen Dateien.) diff --git a/app.js b/app.js index 6258cbd..ae73105 100644 --- a/app.js +++ b/app.js @@ -3,14 +3,12 @@ * Haupt-Application */ -const PLAYER_NAME = 'Kiesewetter, Lara'; +/* global $, parsePGN, filterLaraGames, getLiveGame, getLatestGame, Chess, Chessboard */ let board = null; let chess = null; let currentGame = null; let allLaraGames = []; -let serverLastFetch = null; -let laraColor = null; let currentMoveIndex = -1; let userSelectedGame = false; let userScrolledMoves = false; @@ -89,14 +87,13 @@ function updateBoard() { // Spiegele das Brett, wenn Lara Schwarz hat const laraIsBlack = currentGame.black.toLowerCase().includes('kiesewetter'); const orientation = laraIsBlack ? 'black' : 'white'; - laraColor = laraIsBlack ? 'b' : 'w'; // Führe alle Züge aus const nonResultMoves = currentGame.moves.filter(m => !m.isResult); for (const move of nonResultMoves) { try { chess.move(move.san); - } catch (e) { + } catch { // Ignoriere ungültige Züge } } @@ -108,7 +105,7 @@ function updateBoard() { for (let i = 0; i <= currentMoveIndex && i < nonResultMoves.length; i++) { try { chess.move(nonResultMoves[i].san); - } catch (e) { + } catch { break; } } @@ -153,7 +150,7 @@ function goToMove(index) { for (let i = 0; i <= index; i++) { try { chess.move(nonResultMoves[i].san); - } catch (err) { + } catch { break; } } @@ -265,21 +262,19 @@ function highlightActivePlayer() { * Highlight den letzten Zug auf dem Brett */ function highlightLastMove() { - if (!board || !chess) return; + if (!board || !chess || !currentGame) return; + + $('#board [data-square]').removeClass('last-move-highlight'); const nonResultMoves = currentGame.moves.filter(m => !m.isResult); if (currentMoveIndex >= 0 && currentMoveIndex < nonResultMoves.length) { - const lastMove = nonResultMoves[currentMoveIndex]; - - // Parse die SAN-Züge, um Start- und Zielfelder zu finden const moves = chess.history({ verbose: true }); if (moves.length > 0) { const lastMoveData = moves[moves.length - 1]; - board.highlightSquare(lastMoveData.from, lastMoveData.to); + $(`#board [data-square="${lastMoveData.from}"]`).addClass('last-move-highlight'); + $(`#board [data-square="${lastMoveData.to}"]`).addClass('last-move-highlight'); } - } else { - board.clearHighlights(); } } @@ -501,12 +496,11 @@ async function updateStandings() { ${data.losses} `; - serverLastFetch = Date.now(); return; } } document.getElementById('standings-content').innerHTML = '
Daten nicht verfügbar
'; - } catch (err) { + } catch { document.getElementById('standings-content').innerHTML = '
Daten nicht verfügbar
'; } } @@ -564,11 +558,6 @@ function showLoading(show) { document.getElementById('loading-overlay').style.display = show ? 'flex' : 'none'; } -function showError(msg) { - document.getElementById('error-message').textContent = msg; - document.getElementById('error-overlay').style.display = 'flex'; -} - function hideError() { document.getElementById('error-overlay').style.display = 'none'; } @@ -609,8 +598,6 @@ document.getElementById('copy-pgn-btn').addEventListener('click', async () => { document.addEventListener('keydown', (e) => { if (!currentGame) return; - const nonResultMoves = currentGame.moves.filter(m => !m.isResult); - if (e.key === 'ArrowLeft') { e.preventDefault(); goToMove(currentMoveIndex - 1); diff --git a/build-less.js b/build-less.js index 467e1b1..21d4aae 100644 --- a/build-less.js +++ b/build-less.js @@ -1,3 +1,4 @@ +/* global require, __dirname, process */ const less = require('less'); const fs = require('fs'); const path = require('path'); diff --git a/eslint.config.mjs b/eslint.config.mjs index 3cce36a..667eb79 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -7,7 +7,7 @@ import { defineConfig } from "eslint/config"; export default defineConfig([ { files: ["**/*.{js,mjs,cjs}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.browser } }, - { files: ["**/*.json"], plugins: { json }, language: "json/json", extends: ["json/recommended"] }, + { files: ["**/*.json"], ignores: ["package-lock.json"], plugins: { json }, language: "json/json", extends: ["json/recommended"] }, { files: ["**/*.md"], plugins: { markdown }, language: "markdown/commonmark", extends: ["markdown/recommended"] }, - { files: ["**/*.css"], plugins: { css }, language: "css/css", extends: ["css/recommended"] }, + { files: ["**/*.css"], plugins: { css }, language: "css/css", extends: ["css/recommended"], rules: { "css/use-baseline": "off" } }, ]); diff --git a/pgn-parser.js b/pgn-parser.js index e02b315..8641993 100644 --- a/pgn-parser.js +++ b/pgn-parser.js @@ -130,3 +130,8 @@ function getLatestGame(laraGames) { }); return sorted[0]; } + +window.parsePGN = parsePGN; +window.filterLaraGames = filterLaraGames; +window.getLiveGame = getLiveGame; +window.getLatestGame = getLatestGame; diff --git a/style.css b/style.css index 11cea79..27e49e1 100644 --- a/style.css +++ b/style.css @@ -130,6 +130,9 @@ header h1 { width: 100%; max-width: 500px; } +#board [data-square].last-move-highlight { + box-shadow: inset 0 0 3px 3px rgba(255, 200, 0, 0.7); +} #pgn-panel { width: 100%; max-width: 500px; @@ -172,6 +175,7 @@ header h1 { padding: 8px; background: rgba(0, 0, 0, 0.4); border-radius: 6px; + -webkit-user-select: text; user-select: text; } /* Info Section */ diff --git a/style.less b/style.less index 0923b8f..6895b30 100644 --- a/style.less +++ b/style.less @@ -157,6 +157,10 @@ header { #board { width: 100%; max-width: 500px; + + [data-square].last-move-highlight { + box-shadow: inset 0 0 3px 3px rgba(255, 200, 0, 0.7); + } } #pgn-panel { @@ -205,6 +209,7 @@ header { padding: 8px; background: @bg-darker; border-radius: 6px; + -webkit-user-select: text; user-select: text; }