mirror of
https://github.com/tiennm99/sokoban.git
synced 2026-05-23 10:25:19 +00:00
8a3d4b4a9d
Replace Phaser 3 with Svelte 5 as the rendering and UI layer. The framework-agnostic core (level parser, board model, progress store, microban level data) moves from src/game/core → src/lib/core with zero code changes. Scenes and the hand-rolled button factory are gone; in their place: - src/App.svelte root router (menu / levels / game) - src/views/MenuView title + play + progress + hints - src/views/LevelSelectView paginated 5x4 grid with native <button>s - src/views/GameView owns BoardModel, handles input, HUD, win - src/views/Board purely presentational DOM renderer - src/views/AppButton shared themed wrapper for native <button> - src/app.css Nord palette ported to CSS variables GameView uses a non-reactive BoardModel ref and syncs plain snapshot fields (player, boxes, moves, won) into $state after every mutation — Board consumes only plain props, so Svelte reactivity stays predictable and the core class stays framework-agnostic. GameView is keyed on levelIndex in App, so changing level remounts with fresh state. Native <button> everywhere kills the click-hitbox class of bugs. Animations are now CSS transform transitions (110ms) instead of tweens. Bundle shrinks from ~1.5 MB Phaser to ~65 kB JS / 23 kB gzipped — about 60x smaller. Removed: phaser, terser, src/game, log.js (analytics ping), phasermsg vite plugin, manual Phaser chunks, terser config, public/style.css. Scripts simplified to dev/build. Docs updated: codebase summary, architecture, code standards, changelog, roadmap, README.
40 lines
2.1 KiB
Markdown
40 lines
2.1 KiB
Markdown
# Code Standards
|
|
|
|
## Language & Toolchain
|
|
- ES modules, modern JS (no TypeScript).
|
|
- Svelte 5 with runes (`$state`, `$derived`, `$props`).
|
|
- Vite as build tool. Dev: `npm run dev`. Prod: `npm run build`.
|
|
|
|
## Naming
|
|
- Plain JS files: **kebab-case** with descriptive names (`board-model.js`, `progress-store.js`).
|
|
- Svelte components: **PascalCase.svelte** per ecosystem convention (`MenuView.svelte`, `AppButton.svelte`).
|
|
- Classes: PascalCase (`BoardModel`).
|
|
- Functions and variables: camelCase.
|
|
- Constants: UPPER_SNAKE for module-level tuning knobs (`REPEAT_MS`, `PER_PAGE`).
|
|
|
|
## File size
|
|
- Code files must stay under 200 lines of code.
|
|
- Pure-data files (levels, palettes) are exempt.
|
|
|
|
## Architecture rules
|
|
- **Views** (`src/views/*.svelte`) own layout + user interaction. Each screen is one component, kept under 200 LOC.
|
|
- **Core** (`src/lib/core/`) is pure JS — no Svelte imports. Anything that can be unit-tested without a DOM lives here (parser, board model, progress store).
|
|
- **Data** (`src/lib/data/`) is framework-agnostic static data.
|
|
- `Board.svelte` is purely presentational: plain props in, DOM out. It does not import or touch `BoardModel`.
|
|
- `GameView.svelte` owns the mutable `BoardModel` instance and calls `syncFromModel()` after every mutation to reassign the reactive `$state` snapshots that `Board` consumes.
|
|
- No new dependencies without updating this doc.
|
|
|
|
## Style
|
|
- Prefer composition over inheritance.
|
|
- Fail loudly during development (console.error on unexpected state), fail gracefully at runtime (try/catch around level parsing, progress store).
|
|
- Comments: short, explain *why*, not *what*. File headers give a one-sentence purpose.
|
|
|
|
## Git / commits
|
|
- Conventional commits (`feat:`, `fix:`, `refactor:`, `docs:`, `chore:`).
|
|
- Never commit dotenv, keys, or build artifacts.
|
|
- Run `npm run build-nolog` before pushing to catch compile errors.
|
|
|
|
## Testing strategy (current)
|
|
No automated tests yet. Manual smoke test: load menu → play level 1 → complete → verify progress saved in localStorage → reload page → verify completion persists.
|
|
Future: unit tests for `level-parser.js` and `board-model.js` (both framework-free JS).
|