From 75b293125b5c7ab31c3bd45d31e17729cb957d22 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 10:20:09 +0000
Subject: [PATCH 01/16] feat: add Lode Runner Level 1 game to the arcade
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/01fcfc31-3bd3-41a8-bf1f-b06ceaca6af4
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
src/_includes/scripts.njk | 1 +
src/assets/js/games/game-manager.js | 6 +
src/assets/js/games/lode-runner.js | 534 ++++++++++++++++++++++++++++
src/assets/js/script.js | 1 +
src/games.njk | 32 +-
5 files changed, 572 insertions(+), 2 deletions(-)
create mode 100644 src/assets/js/games/lode-runner.js
diff --git a/src/_includes/scripts.njk b/src/_includes/scripts.njk
index 8705f65..e42c9b7 100644
--- a/src/_includes/scripts.njk
+++ b/src/_includes/scripts.njk
@@ -11,4 +11,5 @@
+
diff --git a/src/assets/js/games/game-manager.js b/src/assets/js/games/game-manager.js
index cfe089d..3d28c9e 100644
--- a/src/assets/js/games/game-manager.js
+++ b/src/assets/js/games/game-manager.js
@@ -156,6 +156,12 @@ const GameManager = (() => {
desc: "Played 5 Developer Duels!",
xp: 75,
},
+ lode_runner_win: {
+ emoji: "đ",
+ name: "Lode Star",
+ desc: "Collected all gold in Lode Runner Level 1!",
+ xp: 75,
+ },
};
/** Returns the full achievements object stored in localStorage. */
diff --git a/src/assets/js/games/lode-runner.js b/src/assets/js/games/lode-runner.js
new file mode 100644
index 0000000..c2d2c99
--- /dev/null
+++ b/src/assets/js/games/lode-runner.js
@@ -0,0 +1,534 @@
+/**
+ * lode-runner.js â Lode Runner, Level 1.
+ *
+ * Classic grid-based platformer. Collect all the gold and avoid the guards!
+ *
+ * Controls:
+ * Arrow keys â move left / right / climb up or down a ladder
+ * Z â dig hole to the left (must be standing on solid ground)
+ * X â dig hole to the right (must be standing on solid ground)
+ * ESC â quit
+ *
+ * Theme-aware: reads dark / light mode at startup.
+ */
+
+const LoadRunner = (() => {
+ const GAME_ID = "lode-runner";
+ const TILE = 28; // px per grid cell
+ const COLS = 28;
+ const ROWS = 16;
+ const MOVE_MS = 150; // ms per player step
+ const GUARD_MS = 400; // ms per guard step
+
+ // ââ Tile-type constants âââââââââââââââââââââââââââââââââââââââââââââââââ
+ const MT = { EMPTY: 0, BRICK: 1, STEEL: 2, LADDER: 3, ROPE: 4, GOLD: 5 };
+ const E = MT.EMPTY, B = MT.BRICK, S = MT.STEEL,
+ H = MT.LADDER, G = MT.GOLD;
+
+ // ââ Level 1 layout â 16 rows à 28 columns ââââââââââââââââââââââââââââââ
+ //
+ // Floors: rows 3, 6, 9, 12, 15 (15 = indestructible steel floor)
+ // Ladders: rows 4-9 at cols 5 & 22 ; rows 10-14 at cols 5 & 16
+ // Gold: rows 2, 5, 8, 11
+ // Gap: row 9 col 12 (fall-through shortcut between upper floors)
+ //
+ // Player start : row 14 col 1
+ // Guards start : row 14 cols 9 & 20
+ //
+ /* eslint-disable no-multi-spaces */
+ const LEVEL = [
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
+ [S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S], // 0
+ [S, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, S], // 1
+ [S, E, G, E, E, E, E, G, E, E, E, G, E, E, E, E, G, E, E, E, E, G, E, E, E, E, E, S], // 2
+ [S, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, S], // 3
+ [S, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, H, E, E, E, E, S], // 4
+ [S, E, E, G, E, H, E, E, G, E, E, E, G, E, E, E, G, E, E, E, E, E, H, E, E, G, E, S], // 5
+ [S, B, B, B, B, H, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, H, B, B, B, B, S], // 6
+ [S, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, H, E, E, E, E, S], // 7
+ [S, E, E, G, E, H, E, E, E, G, E, E, E, E, G, E, E, E, E, E, E, E, H, E, E, G, E, S], // 8
+ [S, B, B, B, B, B, B, B, B, B, B, B, E, B, B, B, B, B, B, B, B, B, B, B, B, B, B, S], // 9 â gap col 12
+ [S, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, S], // 10
+ [S, E, E, G, E, H, E, E, G, E, E, E, E, G, E, E, H, E, E, G, E, E, E, E, E, G, E, S], // 11
+ [S, B, B, B, B, H, B, B, B, B, B, B, B, B, B, B, H, B, B, B, B, B, B, B, B, B, B, S], // 12
+ [S, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, S], // 13
+ [S, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, H, E, E, E, E, E, E, E, E, E, E, S], // 14
+ [S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S, S], // 15
+ ];
+ /* eslint-enable no-multi-spaces */
+
+ const PLAYER_START = { r: 14, c: 1 };
+ const GUARD_STARTS = [
+ { r: 14, c: 9, dir: 1 },
+ { r: 14, c: 20, dir: -1 },
+ ];
+
+ const DIG_FILL_MS = 6000; // ms before a dug hole refills
+
+ // ââ Public entry-point ââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function launch() {
+ GameManager.loadPhaser(() => _init());
+ }
+
+ // ââ Initialisation ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _init() {
+ const theme = getGameTheme();
+ const W = COLS * TILE;
+ const H = ROWS * TILE;
+
+ GameManager.destroy(GAME_ID);
+ GameManager.destroyOverlay(GAME_ID);
+
+ const overlay = GameManager.createOverlay(GAME_ID);
+
+ const titleBar = document.createElement("div");
+ titleBar.style.cssText =
+ "color:#fff;font-size:0.85rem;font-weight:900;text-transform:uppercase;" +
+ "letter-spacing:0.15em;margin-bottom:0.5rem;opacity:0.8;";
+ titleBar.textContent = "đ LODE RUNNER â Level 1";
+ overlay.appendChild(titleBar);
+
+ const canvasWrap = document.createElement("div");
+ canvasWrap.style.cssText = "position:relative;";
+ overlay.appendChild(canvasWrap);
+
+ const config = {
+ type: Phaser.AUTO,
+ width: W,
+ height: H,
+ backgroundColor: theme.isDark ? "#0a0c14" : "#cbd5e1",
+ parent: canvasWrap,
+ scene: {
+ create() { _onCreate(this, theme, W, H); },
+ update() { _onUpdate(this); },
+ },
+ };
+
+ const instance = new Phaser.Game(config);
+ GameManager.instances[GAME_ID] = instance;
+ }
+
+ // ââ Scene create ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _onCreate(scene, theme, W, H) {
+ // Deep-copy the level so we can mutate tiles (dig holes)
+ scene.lr_map = LEVEL.map(row => row.slice());
+ scene.lr_active = true;
+ scene.lr_score = 0;
+ scene.lr_goldLeft = 0;
+ scene.lr_digTimers = []; // { r, c, fillAt }
+ scene.lr_playerMoveAt = 0;
+ scene.lr_guardMoveAt = 0;
+ scene.lr_dirty = true;
+
+ // Count gold
+ for (let r = 0; r < ROWS; r++)
+ for (let c = 0; c < COLS; c++)
+ if (scene.lr_map[r][c] === MT.GOLD) scene.lr_goldLeft++;
+
+ // Graphics layers (back-to-front)
+ scene.lr_gfx = scene.add.graphics();
+ scene.lr_playerGfx = scene.add.graphics();
+ scene.lr_guardGfx = scene.add.graphics();
+
+ // Player
+ scene.lr_player = { r: PLAYER_START.r, c: PLAYER_START.c };
+
+ // Guards
+ scene.lr_guards = GUARD_STARTS.map(g => ({
+ r: g.r, c: g.c, dir: g.dir,
+ startR: g.r, startC: g.c, startDir: g.dir,
+ respawnAt: 0,
+ }));
+
+ // HUD texts
+ const hudStyle = {
+ fontSize: "12px",
+ fill: theme.isDark ? "#e2e8f0" : "#1e293b",
+ fontStyle: "bold",
+ };
+ scene.lr_goldText = scene.add
+ .text(8, 3, "Gold: " + scene.lr_goldLeft, hudStyle)
+ .setDepth(10);
+ scene.lr_scoreText = scene.add
+ .text(W - 8, 3, "Score: 0", hudStyle)
+ .setOrigin(1, 0)
+ .setDepth(10);
+ scene.add
+ .text(
+ W / 2, H - 2,
+ "Arrows: move/climb Z: dig left X: dig right ESC: quit",
+ { fontSize: "9px", fill: "#94a3b8" },
+ )
+ .setOrigin(0.5, 1)
+ .setDepth(10);
+
+ // Input
+ scene.lr_cursors = scene.input.keyboard.createCursorKeys();
+ scene.lr_keyZ = scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Z);
+ scene.lr_keyX = scene.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.X);
+ scene.input.keyboard.once("keydown-ESC", _cleanup);
+
+ GameManager.incrementStat("load_runner_plays");
+ _draw(scene, theme);
+ }
+
+ // ââ Scene update ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _onUpdate(scene) {
+ if (!scene.lr_active) return;
+
+ const now = scene.time.now;
+ const theme = getGameTheme();
+
+ // ââ Refill dug bricks ââ
+ const before = scene.lr_digTimers.length;
+ scene.lr_digTimers = scene.lr_digTimers.filter(dt => {
+ if (now < dt.fillAt) return true;
+ const p = scene.lr_player;
+ const occupied =
+ (p.r === dt.r && p.c === dt.c) ||
+ scene.lr_guards.some(g => g.r === dt.r && g.c === dt.c);
+ if (!occupied) {
+ scene.lr_map[dt.r][dt.c] = MT.BRICK;
+ scene.lr_dirty = true;
+ return false;
+ }
+ dt.fillAt = now + 1000; // retry in 1 s
+ return true;
+ });
+ if (scene.lr_digTimers.length !== before) scene.lr_dirty = true;
+
+ // ââ Player turn ââ
+ if (now >= scene.lr_playerMoveAt) {
+ const moved = _playerTurn(scene);
+ if (moved) {
+ scene.lr_playerMoveAt = now + MOVE_MS;
+ scene.lr_dirty = true;
+ _checkGold(scene);
+ _checkDeath(scene);
+ }
+ }
+
+ // ââ Guard turns ââ
+ if (now >= scene.lr_guardMoveAt) {
+ _guardTurns(scene, now);
+ scene.lr_guardMoveAt = now + GUARD_MS;
+ scene.lr_dirty = true;
+ _checkDeath(scene);
+ }
+
+ // ââ Redraw only when something changed ââ
+ if (scene.lr_dirty && scene.lr_active) {
+ _draw(scene, theme);
+ scene.lr_dirty = false;
+ }
+ }
+
+ // ââ Player input & movement âââââââââââââââââââââââââââââââââââââââââââââ
+ function _playerTurn(scene) {
+ const p = scene.lr_player;
+ const map = scene.lr_map;
+ const cur = scene.lr_cursors;
+
+ // Gravity first (takes priority over deliberate input)
+ if (_fallOne(p, map)) return true;
+
+ // Dig actions
+ if (Phaser.Input.Keyboard.JustDown(scene.lr_keyZ)) return _dig(scene, p, -1);
+ if (Phaser.Input.Keyboard.JustDown(scene.lr_keyX)) return _dig(scene, p, 1);
+
+ // Directional movement
+ if (cur.left.isDown) return _walk(p, map, 0, -1);
+ if (cur.right.isDown) return _walk(p, map, 0, 1);
+ if (cur.up.isDown) return _walk(p, map, -1, 0);
+ if (cur.down.isDown) return _walk(p, map, 1, 0);
+
+ return false;
+ }
+
+ /**
+ * Attempt to move entity one grid step. Returns true if the move succeeded.
+ * Works for both the player and guards.
+ */
+ function _walk(entity, map, dr, dc) {
+ const nr = entity.r + dr;
+ const nc = entity.c + dc;
+ if (nr < 0 || nr >= ROWS || nc < 0 || nc >= COLS) return false;
+
+ const curTile = map[entity.r][entity.c];
+ const destTile = map[nr][nc];
+ const belowCur = entity.r + 1 < ROWS ? map[entity.r + 1][entity.c] : MT.STEEL;
+
+ // Solid tiles are impassable
+ if (destTile === MT.BRICK || destTile === MT.STEEL) return false;
+
+ if (dr === -1) {
+ // Moving UP: only on a ladder
+ if (curTile !== MT.LADDER) return false;
+ }
+
+ if (dr === 1) {
+ // Moving DOWN: entity must currently be on a ladder, or dest is a ladder
+ if (curTile !== MT.LADDER && destTile !== MT.LADDER) return false;
+ }
+
+ if (dc !== 0) {
+ // Horizontal movement requires solid ground, a ladder, or a rope underfoot
+ const onGround = belowCur === MT.BRICK || belowCur === MT.STEEL;
+ const onLadder = curTile === MT.LADDER;
+ const onRope = curTile === MT.ROPE;
+ if (!onGround && !onLadder && !onRope) return false;
+ }
+
+ entity.r = nr;
+ entity.c = nc;
+ return true;
+ }
+
+ /** Drop entity one row if not supported. Returns true if it fell. */
+ function _fallOne(entity, map) {
+ const curTile = map[entity.r][entity.c];
+ const belowTile = entity.r + 1 < ROWS ? map[entity.r + 1][entity.c] : MT.STEEL;
+
+ if (curTile === MT.LADDER || curTile === MT.ROPE) return false;
+ if (belowTile === MT.BRICK || belowTile === MT.STEEL || belowTile === MT.LADDER) return false;
+
+ if (entity.r + 1 < ROWS) { entity.r++; return true; }
+ return false;
+ }
+
+ /**
+ * Dig the brick one row below the player, one column to the side (dc = Âą1).
+ * Only legal when standing on solid ground next to a diggable brick.
+ */
+ function _dig(scene, player, dc) {
+ const tr = player.r + 1; // target row = floor level
+ const tc = player.c + dc; // target col = one tile to the side
+
+ if (tr >= ROWS || tc < 0 || tc >= COLS) return false;
+ if (scene.lr_map[tr][tc] !== MT.BRICK) return false;
+
+ // Player must be standing on solid ground (not on a ladder / rope / falling)
+ const belowPlayer = tr < ROWS ? scene.lr_map[tr][player.c] : MT.STEEL;
+ if (belowPlayer !== MT.BRICK && belowPlayer !== MT.STEEL) return false;
+
+ scene.lr_map[tr][tc] = MT.EMPTY;
+ scene.lr_digTimers.push({ r: tr, c: tc, fillAt: scene.time.now + DIG_FILL_MS });
+ return true;
+ }
+
+ // ââ Guard AI ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _guardTurns(scene, now) {
+ const map = scene.lr_map;
+ const p = scene.lr_player;
+
+ for (const g of scene.lr_guards) {
+ // Waiting to respawn after falling into a dug hole
+ if (g.respawnAt > 0) {
+ if (now >= g.respawnAt) {
+ g.r = g.startR; g.c = g.startC; g.dir = g.startDir;
+ g.respawnAt = 0;
+ }
+ continue;
+ }
+
+ // Detect if guard has fallen into a dug hole
+ const inHole = scene.lr_digTimers.some(dt => dt.r === g.r && dt.c === g.c);
+ if (inHole) {
+ g.respawnAt = now + 4000; // trapped for 4 s then respawn
+ continue;
+ }
+
+ // Gravity
+ if (_fallOne(g, map)) continue;
+
+ // On a ladder â chase player vertically
+ if (map[g.r][g.c] === MT.LADDER) {
+ const dr = p.r < g.r ? -1 : 1;
+ if (_walk(g, map, dr, 0)) continue;
+ }
+
+ // Horizontal patrol: try to move toward player, reverse on block
+ const targetDir = p.c >= g.c ? 1 : -1;
+ if (g.dir !== targetDir) g.dir = targetDir; // face player
+ if (!_walk(g, map, 0, g.dir)) {
+ g.dir = -g.dir;
+ _walk(g, map, 0, g.dir);
+ }
+ }
+ }
+
+ // ââ Gold collection âââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _checkGold(scene) {
+ const p = scene.lr_player;
+ if (scene.lr_map[p.r][p.c] !== MT.GOLD) return;
+
+ scene.lr_map[p.r][p.c] = MT.EMPTY;
+ scene.lr_goldLeft--;
+ scene.lr_score += 100;
+ scene.lr_goldText.setText("Gold: " + scene.lr_goldLeft);
+ scene.lr_scoreText.setText("Score: " + scene.lr_score);
+ GameManager.awardXP(5);
+
+ if (scene.lr_goldLeft <= 0) _onVictory(scene);
+ }
+
+ // ââ Guard collision âââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _checkDeath(scene) {
+ if (!scene.lr_active) return;
+ const p = scene.lr_player;
+ for (const g of scene.lr_guards) {
+ if (g.respawnAt > 0) continue; // guard trapped, harmless
+ if (g.r === p.r && g.c === p.c) { _onDefeat(scene); return; }
+ }
+ }
+
+ // ââ Win / Lose screens ââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _onVictory(scene) {
+ if (!scene.lr_active) return;
+ scene.lr_active = false;
+
+ GameManager.awardXP(_XP_LOAD_RUNNER_WIN);
+ GameManager.setHighScore(GAME_ID, scene.lr_score);
+ GameManager.grantAchievement("lode_runner_win");
+
+ const W = COLS * TILE, H = ROWS * TILE;
+ _showEnd(
+ scene, W, H,
+ "đ LEVEL COMPLETE!", "#fbbf24",
+ "+" + _XP_LOAD_RUNNER_WIN + " XP âĸ Score: " + scene.lr_score,
+ );
+ }
+
+ function _onDefeat(scene) {
+ if (!scene.lr_active) return;
+ scene.lr_active = false;
+ const W = COLS * TILE, H = ROWS * TILE;
+ _showEnd(scene, W, H, "đ CAUGHT!", "#ef4444", "Try again!");
+ }
+
+ function _showEnd(scene, W, H, headline, color, sub) {
+ scene.add.rectangle(W / 2, H / 2, W, H, 0x000000, 0.75).setDepth(20);
+ scene.add
+ .text(W / 2, H / 2 - 32, headline, {
+ fontSize: "30px", fill: color,
+ fontStyle: "bold", stroke: "#000000", strokeThickness: 4,
+ })
+ .setOrigin(0.5)
+ .setDepth(21);
+ scene.add
+ .text(W / 2, H / 2 + 14, sub, { fontSize: "18px", fill: "#ffffff" })
+ .setOrigin(0.5)
+ .setDepth(21);
+ scene.add
+ .text(W / 2, H / 2 + 56, "Click or press ESC to close", {
+ fontSize: "11px", fill: "#ffffff",
+ })
+ .setOrigin(0.5)
+ .setDepth(21);
+ scene.input.once("pointerdown", _cleanup);
+ scene.input.keyboard.once("keydown-ESC", _cleanup);
+ }
+
+ function _cleanup() {
+ GameManager.destroy(GAME_ID);
+ GameManager.destroyOverlay(GAME_ID);
+ }
+
+ // ââ Rendering âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ function _draw(scene, theme) {
+ const T = TILE;
+ const isDark = theme.isDark;
+ const map = scene.lr_map;
+ const gfx = scene.lr_gfx;
+ gfx.clear();
+
+ for (let r = 0; r < ROWS; r++) {
+ for (let c = 0; c < COLS; c++) {
+ const tile = map[r][c];
+ const x = c * T, y = r * T;
+
+ if (tile === MT.STEEL) {
+ gfx.fillStyle(isDark ? 0x334155 : 0x64748b, 1);
+ gfx.fillRect(x, y, T, T);
+ gfx.lineStyle(1, isDark ? 0x475569 : 0x475569, 0.6);
+ gfx.strokeRect(x, y, T, T);
+
+ } else if (tile === MT.BRICK) {
+ gfx.fillStyle(isDark ? 0x6d28d9 : 0x7c3aed, 1);
+ gfx.fillRect(x, y, T, T);
+ gfx.lineStyle(1, isDark ? 0x4c1d95 : 0x5b21b6, 0.9);
+ gfx.strokeRect(x, y, T, T);
+ // horizontal mortar line
+ gfx.beginPath();
+ gfx.moveTo(x, y + T / 2); gfx.lineTo(x + T, y + T / 2);
+ gfx.strokePath();
+ // vertical mortar offset per row
+ const vx = r % 2 === 0 ? x + T / 2 : x;
+ gfx.beginPath();
+ gfx.moveTo(vx, y); gfx.lineTo(vx, y + T / 2);
+ gfx.strokePath();
+
+ } else if (tile === MT.LADDER) {
+ // Draw two rails and three rungs
+ gfx.lineStyle(2, 0xfbbf24, 1);
+ gfx.beginPath();
+ gfx.moveTo(x + T * 0.28, y); gfx.lineTo(x + T * 0.28, y + T);
+ gfx.moveTo(x + T * 0.72, y); gfx.lineTo(x + T * 0.72, y + T);
+ gfx.strokePath();
+ for (let rung = 0; rung <= 2; rung++) {
+ gfx.beginPath();
+ gfx.moveTo(x + T * 0.28, y + rung * T / 2);
+ gfx.lineTo(x + T * 0.72, y + rung * T / 2);
+ gfx.strokePath();
+ }
+
+ } else if (tile === MT.ROPE) {
+ gfx.lineStyle(2, 0x78716c, 1);
+ gfx.beginPath();
+ gfx.moveTo(x, y + T * 0.3); gfx.lineTo(x + T, y + T * 0.3);
+ gfx.strokePath();
+
+ } else if (tile === MT.GOLD) {
+ gfx.fillStyle(0xfbbf24, 1);
+ gfx.fillCircle(x + T / 2, y + T / 2, T * 0.22);
+ gfx.lineStyle(1.5, 0xd97706, 1);
+ gfx.strokeCircle(x + T / 2, y + T / 2, T * 0.22);
+ }
+ }
+ }
+
+ // ââ Player (blue runner) ââ
+ const pg = scene.lr_playerGfx;
+ pg.clear();
+ const p = scene.lr_player;
+ const px = p.c * T, py = p.r * T;
+ // head
+ pg.fillStyle(0xfde68a, 1);
+ pg.fillCircle(px + T * 0.5, py + T * 0.2, T * 0.16);
+ // body
+ pg.fillStyle(0x3b82f6, 1);
+ pg.fillRect(px + T * 0.25, py + T * 0.36, T * 0.5, T * 0.38);
+ // legs
+ pg.fillStyle(0x1d4ed8, 1);
+ pg.fillRect(px + T * 0.22, py + T * 0.74, T * 0.22, T * 0.22);
+ pg.fillRect(px + T * 0.56, py + T * 0.74, T * 0.22, T * 0.22);
+
+ // ââ Guards (red) ââ
+ const gg = scene.lr_guardGfx;
+ gg.clear();
+ for (const g of scene.lr_guards) {
+ if (g.respawnAt > 0) continue; // don't draw while respawning
+ const gx = g.c * T, gy = g.r * T;
+ gg.fillStyle(0xfca5a5, 1); // head
+ gg.fillCircle(gx + T * 0.5, gy + T * 0.2, T * 0.16);
+ gg.fillStyle(0xef4444, 1); // body
+ gg.fillRect(gx + T * 0.25, gy + T * 0.36, T * 0.5, T * 0.38);
+ gg.fillStyle(0x991b1b, 1); // legs
+ gg.fillRect(gx + T * 0.22, gy + T * 0.74, T * 0.22, T * 0.22);
+ gg.fillRect(gx + T * 0.56, gy + T * 0.74, T * 0.22, T * 0.22);
+ }
+ }
+
+ // ââ Public API ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
+ return { launch };
+})();
diff --git a/src/assets/js/script.js b/src/assets/js/script.js
index 9e7637f..7ac1311 100644
--- a/src/assets/js/script.js
+++ b/src/assets/js/script.js
@@ -46,6 +46,7 @@ const XP_SPACE_INVADERS_WIN = 200; // Defeat all Space Invaders
const _XP_CODE_BREAKER_WIN = 100; // Win a Code Breaker round
const _XP_DEV_DUEL_PLAY = 25; // Play a Developer Duel
const _XP_DEV_DUEL_WIN = 50; // Win a Developer Duel
+const _XP_LOAD_RUNNER_WIN = 150; // Complete Lode Runner Level 1
const NUM_LEVELS = LEVELS.length;
diff --git a/src/games.njk b/src/games.njk
index 39a792e..959a1b5 100644
--- a/src/games.njk
+++ b/src/games.njk
@@ -23,7 +23,7 @@ permalink: /games/
{# ââ High-score strip ââ #}
-
+
Space Invaders
â
@@ -39,10 +39,15 @@ permalink: /games/
â
High Score
+
+
Lode Runner
+
â
+
High Score
+
{# ââ Game cards ââ #}
-
+
{# Space Invaders #}
@@ -80,6 +85,20 @@ permalink: /games/
+ {# Lode Runner #}
+
+
đ
+
Lode Runner
+
Classic grid platformer â collect all the gold while dodging guards! Dig holes to trap them. Earn +{{ _XP_LOAD_RUNNER_WIN or 150 }} XP for clearing Level 1.
+
+ Arrows: move/climb Z: dig left X: dig right
+
+
+ đ Play
+
+
+
{# ââ Achievements ââ #}
@@ -112,6 +131,14 @@ permalink: /games/
Locked
+
@@ -127,6 +154,7 @@ permalink: /games/
"space-invaders": document.getElementById("hs-space-invaders"),
"code-breaker": document.getElementById("hs-code-breaker"),
"dev-duel": document.getElementById("hs-dev-duel"),
+ "lode-runner": document.getElementById("hs-lode-runner"),
};
Object.keys(scores).forEach(function (id) {
var val = parseInt(localStorage.getItem("hs_" + id)) || 0;
From 069b6ae4439bb4050a09519bf7ba1365609d4f5c Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:06:50 +1000
Subject: [PATCH 02/16] docs: Add GitHub CLI alternative for contributing
workflow (#420)
* Add GitHub CLI contributing section to README
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/a4b976e4-10d8-406a-a686-7eb6217202a8
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
* Fix GitHub CLI section placement and ToC order in README
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/17aecb28-afd3-40b6-9bae-942ced043323
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
* Disable MD024 and MD051 in markdownlint config
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/ed8e1077-c03c-461a-ba62-0ae39a857eea
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
.github/linters/.markdown-lint.yml | 6 ++
README.md | 92 ++++++++++++++++++++++++++++++
2 files changed, 98 insertions(+)
diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml
index 29bc4a5..cafb156 100644
--- a/.github/linters/.markdown-lint.yml
+++ b/.github/linters/.markdown-lint.yml
@@ -3,6 +3,12 @@
# MD013/line-length Line length
MD013: false
+# MD024/no-duplicate-heading No duplicate headings
+MD024: false
+
+# MD051/link-fragments Link fragments
+MD051: false
+
# MD033/no-inline-html Inline HTML
MD033: false
diff --git a/README.md b/README.md
index 54e7d0f..2016d76 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@
- [YAML File Format](#-yaml-file-format)
- [Local Development](#-local-development-optional)
- [Git Workflow & Keeping in Sync](#-git-workflow--keeping-in-sync)
+- [Contributing with GitHub CLI](#-contributing-with-github-cli)
- [Contribution Guidelines](#-contribution-guidelines)
- [Troubleshooting](#-troubleshooting--faq)
- [License](#-license)
@@ -555,6 +556,97 @@ git push origin my-feature-branch --force-with-lease
---
+## đĨī¸ Contributing with GitHub CLI
+
+Prefer the terminal over the browser? The [GitHub CLI (`gh`)](https://cli.github.com/) lets you complete the entire contribution workflow without leaving your command line. Install it from and authenticate once with `gh auth login`.
+
+### Step 1: Fork the Repository
+
+```bash
+# Fork the repo and clone it locally in one command
+gh repo fork NextCommunity/NextCommunity.github.io --clone=true --remote=true
+cd NextCommunity.github.io
+```
+
+The `--remote=true` flag automatically adds the original repo as an `upstream` remote, so you stay in sync without any extra setup.
+
+### Step 2: Create a Feature Branch
+
+```bash
+# Make sure your local main is up to date first
+git checkout main
+git pull upstream main
+
+# Create and switch to a new feature branch
+git checkout -b add-your-github-username
+```
+
+Use a descriptive branch name such as `add-jbampton` or `fix-yaml-typo`.
+
+### Step 3: Create Your Profile File
+
+```bash
+# Navigate to the users directory and create your YAML file
+cp src/users/_template.yaml src/users/your-github-username.yaml
+```
+
+Open `src/users/your-github-username.yaml` in your editor and fill in your details (see [YAML File Format](#-yaml-file-format) for the full field reference).
+
+### Step 4: Test Locally (Optional but Recommended)
+
+```bash
+npm install
+npm start
+```
+
+Visit `http://localhost:8080` to preview your profile before submitting.
+
+### Step 5: Commit and Push
+
+```bash
+# Stage your new profile file
+git add src/users/your-github-username.yaml
+
+# Commit with a descriptive message
+git commit -m "Add [Your Name] to developer directory"
+
+# Push your feature branch to your fork
+git push origin add-your-github-username
+```
+
+### Step 6: Open a Pull Request with `gh`
+
+```bash
+gh pr create \
+ --repo NextCommunity/NextCommunity.github.io \
+ --base main \
+ --title "Add [Your Name] to directory" \
+ --body "Fixes #213
+
+Adding my profile to the NextCommunity developer directory."
+```
+
+The command prints a URL to the newly created PR. That's it â no browser required!
+
+### Step 7: Monitor CI and Respond to Feedback
+
+```bash
+# Watch the status of checks on your PR
+gh pr checks
+
+# View any review comments left by maintainers
+gh pr view --comments
+
+# If changes are requested, edit your file, then commit and push again
+git add src/users/your-github-username.yaml
+git commit -m "Address review feedback"
+git push origin add-your-github-username
+```
+
+Once all checks pass and a maintainer approves the PR, it will be merged and your profile will go live! đ
+
+---
+
## đ¤ Contribution Guidelines
### Code of Conduct
From 25b00affd5c2f2fbd56534919c8c18bc92be9c43 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:16:57 +1000
Subject: [PATCH 03/16] Add push trigger for main branch to manual, audit, and
standards hook workflows (#421)
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/74413ae5-9c4f-4fec-988b-e7e8a7644c22
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
.github/workflows/pre-commit-audit.yml | 5 ++++-
.github/workflows/pre-commit-manual.yml | 5 ++++-
.github/workflows/pre-commit.yml | 5 ++++-
3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/pre-commit-audit.yml b/.github/workflows/pre-commit-audit.yml
index fca9bf2..dbaa578 100644
--- a/.github/workflows/pre-commit-audit.yml
+++ b/.github/workflows/pre-commit-audit.yml
@@ -1,7 +1,10 @@
# https://github.com/j178/prek
name: Audit hooks
-on: [pull_request]
+on:
+ pull_request:
+ push:
+ branches: [main]
permissions:
contents: read
diff --git a/.github/workflows/pre-commit-manual.yml b/.github/workflows/pre-commit-manual.yml
index df26d13..f1f41b0 100644
--- a/.github/workflows/pre-commit-manual.yml
+++ b/.github/workflows/pre-commit-manual.yml
@@ -1,7 +1,10 @@
# https://github.com/j178/prek
name: Manual hooks
-on: [pull_request]
+on:
+ pull_request:
+ push:
+ branches: [main]
permissions:
contents: read
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index 43d74ed..b004cd7 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -1,7 +1,10 @@
# https://github.com/j178/prek
name: Standard hooks
-on: [pull_request]
+on:
+ pull_request:
+ push:
+ branches: [main]
permissions:
contents: read
From f15375479b31bf28359f5c2e895042bf23753d3b Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:27:54 +1000
Subject: [PATCH 04/16] markdownlint: replace MD033 global disable with element
allowlist (#422)
* Initial plan
* fix: whitelist specific HTML elements for MD033 instead of disabling globally
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/ee41597a-a9e7-4bc0-9720-83bcd2e37d7f
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
.github/linters/.markdown-lint.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml
index cafb156..25e15ae 100644
--- a/.github/linters/.markdown-lint.yml
+++ b/.github/linters/.markdown-lint.yml
@@ -10,7 +10,8 @@ MD024: false
MD051: false
# MD033/no-inline-html Inline HTML
-MD033: false
+MD033:
+ allowed_elements: ["div", "h1"]
# MD036/no-emphasis-as-heading Emphasis used instead of a heading
MD036: false
From fb8e9b7637157a5eb0e124c21ccc40e00631902a Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:40:01 +1000
Subject: [PATCH 05/16] Add push trigger on main branch to super-linter
workflow (#425)
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/1f54eb02-130b-4c83-b870-d0aa9e760fa0
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
.github/workflows/super-linter.yml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml
index e31b807..2254218 100644
--- a/.github/workflows/super-linter.yml
+++ b/.github/workflows/super-linter.yml
@@ -1,6 +1,10 @@
name: Super-Linter
-on: [pull_request]
+on:
+ pull_request:
+ push:
+ branches:
+ - main
permissions: {}
From 5b9d69203bbd1dd4982560e05cf4d74897f9adee Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Apr 2026 19:46:02 +1000
Subject: [PATCH 06/16] Pin README status badges to main branch (#424)
* fix: add branch=main to GitHub Actions status badge URLs in README
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/8e809b33-603c-4b8a-b098-e037fcee17e8
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
* Add push trigger for main branch to manual, audit, and standards hook workflows (#421)
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/74413ae5-9c4f-4fec-988b-e7e8a7644c22
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Co-authored-by: John Bampton
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 2016d76..1c8f31a 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,10 @@
[](https://mozilla.github.io/nunjucks/)
[](https://tailwindcss.com/)
-[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/super-linter.yml)
-[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/pre-commit-audit.yml)
-[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/pre-commit-manual.yml)
-[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/pre-commit.yml)
+[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/super-linter.yml?query=branch%3Amain)
+[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/pre-commit-audit.yml?query=branch%3Amain)
+[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/pre-commit-manual.yml?query=branch%3Amain)
+[](https://github.com/NextCommunity/NextCommunity.github.io/actions/workflows/pre-commit.yml?query=branch%3Amain)
[](https://nextcommunity.github.io)
From d6c57cdfef87803b92bbbee00846a70b7362f83a Mon Sep 17 00:00:00 2001
From: John Bampton
Date: Sat, 4 Apr 2026 19:54:45 +1000
Subject: [PATCH 07/16] Update branch naming instructions in README (#426)
Clarify instructions for branch naming in README.
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
README.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/README.md b/README.md
index 1c8f31a..016af0b 100644
--- a/README.md
+++ b/README.md
@@ -100,7 +100,6 @@ git checkout -b my-feature-branch
```
Use a descriptive branch name that reflects your change, e.g. `add-jbampton` or `fix-yaml-typo`.
-Replace `your-github-username` in every example below with the actual branch name you chose here.
### Step 4: Create Your Profile File
From ffd8456bfba11bbea4e4cfa88c691ed1fd98d56b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 7 Apr 2026 02:12:24 +0330
Subject: [PATCH 08/16] Bump esbuild from 0.25.12 to 0.27.4 in the
npm-dependencies group (#433)
Bumps the npm-dependencies group with 1 update: [esbuild](https://github.com/evanw/esbuild).
Updates `esbuild` from 0.25.12 to 0.27.4
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/v0.27.4/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.25.12...v0.27.4)
---
updated-dependencies:
- dependency-name: esbuild
dependency-version: 0.27.4
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: npm-dependencies
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
package-lock.json | 286 +++++++++++++++++++++++++++-------------------
package.json | 2 +-
2 files changed, 167 insertions(+), 121 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 8d9bbd2..1417252 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31,7 +31,7 @@
"tapable": "^2.3.2"
},
"devDependencies": {
- "esbuild": "^0.25.0",
+ "esbuild": "^0.27.4",
"npm-run-all": "^4.1.5",
"postcss-cli": "^11.0.0"
},
@@ -228,9 +228,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
- "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
+ "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
"cpu": [
"ppc64"
],
@@ -245,9 +245,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
- "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
+ "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
"cpu": [
"arm"
],
@@ -262,9 +262,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
- "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
+ "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
"cpu": [
"arm64"
],
@@ -279,9 +279,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
- "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
+ "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
"cpu": [
"x64"
],
@@ -296,9 +296,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
- "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
+ "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
"cpu": [
"arm64"
],
@@ -313,9 +313,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
- "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
+ "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
"cpu": [
"x64"
],
@@ -330,9 +330,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
- "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
"cpu": [
"arm64"
],
@@ -347,9 +347,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
- "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
+ "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
"cpu": [
"x64"
],
@@ -364,9 +364,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
- "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
+ "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
"cpu": [
"arm"
],
@@ -381,9 +381,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
- "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
+ "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
"cpu": [
"arm64"
],
@@ -398,9 +398,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
- "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
+ "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
"cpu": [
"ia32"
],
@@ -415,9 +415,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
- "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
+ "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
"cpu": [
"loong64"
],
@@ -432,9 +432,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
- "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
+ "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
"cpu": [
"mips64el"
],
@@ -449,9 +449,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
- "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
+ "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
"cpu": [
"ppc64"
],
@@ -466,9 +466,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
- "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
+ "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
"cpu": [
"riscv64"
],
@@ -483,9 +483,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
- "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
+ "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
"cpu": [
"s390x"
],
@@ -500,9 +500,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
- "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
+ "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
"cpu": [
"x64"
],
@@ -517,9 +517,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
"cpu": [
"arm64"
],
@@ -534,9 +534,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
- "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
"cpu": [
"x64"
],
@@ -551,9 +551,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
- "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
+ "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
"cpu": [
"arm64"
],
@@ -568,9 +568,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
- "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
+ "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
"cpu": [
"x64"
],
@@ -585,9 +585,9 @@
}
},
"node_modules/@esbuild/openharmony-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
- "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
+ "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
"cpu": [
"arm64"
],
@@ -602,9 +602,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
- "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
+ "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
"cpu": [
"x64"
],
@@ -619,9 +619,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
- "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
+ "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
"cpu": [
"arm64"
],
@@ -636,9 +636,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
- "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
+ "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
"cpu": [
"ia32"
],
@@ -653,9 +653,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
- "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
+ "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
"cpu": [
"x64"
],
@@ -870,9 +870,6 @@
"cpu": [
"arm64"
],
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -889,9 +886,6 @@
"cpu": [
"arm64"
],
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -908,9 +902,6 @@
"cpu": [
"x64"
],
- "libc": [
- "glibc"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -927,9 +918,6 @@
"cpu": [
"x64"
],
- "libc": [
- "musl"
- ],
"license": "MIT",
"optional": true,
"os": [
@@ -968,6 +956,64 @@
"node": ">=14.0.0"
}
},
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
+ "version": "1.8.1",
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
+ "version": "1.8.1",
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
+ "version": "1.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/core": "^1.7.1",
+ "@emnapi/runtime": "^1.7.1",
+ "@tybys/wasm-util": "^0.10.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Brooooooklyn"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
+ "version": "2.8.1",
+ "inBundle": true,
+ "license": "0BSD",
+ "optional": true
+ },
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz",
@@ -1839,9 +1885,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.25.12",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
- "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+ "version": "0.27.4",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
+ "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -1852,32 +1898,32 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.12",
- "@esbuild/android-arm": "0.25.12",
- "@esbuild/android-arm64": "0.25.12",
- "@esbuild/android-x64": "0.25.12",
- "@esbuild/darwin-arm64": "0.25.12",
- "@esbuild/darwin-x64": "0.25.12",
- "@esbuild/freebsd-arm64": "0.25.12",
- "@esbuild/freebsd-x64": "0.25.12",
- "@esbuild/linux-arm": "0.25.12",
- "@esbuild/linux-arm64": "0.25.12",
- "@esbuild/linux-ia32": "0.25.12",
- "@esbuild/linux-loong64": "0.25.12",
- "@esbuild/linux-mips64el": "0.25.12",
- "@esbuild/linux-ppc64": "0.25.12",
- "@esbuild/linux-riscv64": "0.25.12",
- "@esbuild/linux-s390x": "0.25.12",
- "@esbuild/linux-x64": "0.25.12",
- "@esbuild/netbsd-arm64": "0.25.12",
- "@esbuild/netbsd-x64": "0.25.12",
- "@esbuild/openbsd-arm64": "0.25.12",
- "@esbuild/openbsd-x64": "0.25.12",
- "@esbuild/openharmony-arm64": "0.25.12",
- "@esbuild/sunos-x64": "0.25.12",
- "@esbuild/win32-arm64": "0.25.12",
- "@esbuild/win32-ia32": "0.25.12",
- "@esbuild/win32-x64": "0.25.12"
+ "@esbuild/aix-ppc64": "0.27.4",
+ "@esbuild/android-arm": "0.27.4",
+ "@esbuild/android-arm64": "0.27.4",
+ "@esbuild/android-x64": "0.27.4",
+ "@esbuild/darwin-arm64": "0.27.4",
+ "@esbuild/darwin-x64": "0.27.4",
+ "@esbuild/freebsd-arm64": "0.27.4",
+ "@esbuild/freebsd-x64": "0.27.4",
+ "@esbuild/linux-arm": "0.27.4",
+ "@esbuild/linux-arm64": "0.27.4",
+ "@esbuild/linux-ia32": "0.27.4",
+ "@esbuild/linux-loong64": "0.27.4",
+ "@esbuild/linux-mips64el": "0.27.4",
+ "@esbuild/linux-ppc64": "0.27.4",
+ "@esbuild/linux-riscv64": "0.27.4",
+ "@esbuild/linux-s390x": "0.27.4",
+ "@esbuild/linux-x64": "0.27.4",
+ "@esbuild/netbsd-arm64": "0.27.4",
+ "@esbuild/netbsd-x64": "0.27.4",
+ "@esbuild/openbsd-arm64": "0.27.4",
+ "@esbuild/openbsd-x64": "0.27.4",
+ "@esbuild/openharmony-arm64": "0.27.4",
+ "@esbuild/sunos-x64": "0.27.4",
+ "@esbuild/win32-arm64": "0.27.4",
+ "@esbuild/win32-ia32": "0.27.4",
+ "@esbuild/win32-x64": "0.27.4"
}
},
"node_modules/escalade": {
diff --git a/package.json b/package.json
index 79156f8..08f1d65 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
"tapable": "^2.3.2"
},
"devDependencies": {
- "esbuild": "^0.25.0",
+ "esbuild": "^0.27.4",
"npm-run-all": "^4.1.5",
"postcss-cli": "^11.0.0"
},
From 99d7c6e965207cbe97ac3e5bb8ad8f2b7edc6d22 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 8 Apr 2026 23:55:11 +1000
Subject: [PATCH 09/16] Bump super-linter/super-linter in the
github-actions-dependencies group (#434)
Bumps the github-actions-dependencies group with 1 update: [super-linter/super-linter](https://github.com/super-linter/super-linter).
Updates `super-linter/super-linter` from 8.5.0 to 8.6.0
- [Release notes](https://github.com/super-linter/super-linter/releases)
- [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/super-linter/super-linter/compare/61abc07d755095a68f4987d1c2c3d1d64408f1f9...9e863354e3ff62e0727d37183162c4a88873df41)
---
updated-dependencies:
- dependency-name: super-linter/super-linter
dependency-version: 8.6.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: github-actions-dependencies
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
.github/workflows/super-linter.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml
index 2254218..dce3ec7 100644
--- a/.github/workflows/super-linter.yml
+++ b/.github/workflows/super-linter.yml
@@ -24,7 +24,7 @@ jobs:
fetch-depth: 0
persist-credentials: false
- name: Super-Linter
- uses: super-linter/super-linter@61abc07d755095a68f4987d1c2c3d1d64408f1f9 # v8.5.0
+ uses: super-linter/super-linter@9e863354e3ff62e0727d37183162c4a88873df41 # v8.6.0
env:
ERROR_ON_MISSING_EXEC_BIT: true
VALIDATE_EDITORCONFIG: true
From 4f13a4d39a8680d130d42da90a41774dd7818c9c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 9 Apr 2026 15:35:32 +1000
Subject: [PATCH 10/16] Bump liquidjs from 10.25.0 to 10.25.5 (#435)
Bumps [liquidjs](https://github.com/harttle/liquidjs) from 10.25.0 to 10.25.5.
- [Release notes](https://github.com/harttle/liquidjs/releases)
- [Changelog](https://github.com/harttle/liquidjs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harttle/liquidjs/compare/v10.25.0...v10.25.5)
---
updated-dependencies:
- dependency-name: liquidjs
dependency-version: 10.25.5
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
package-lock.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 1417252..7c9099d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3352,9 +3352,9 @@
}
},
"node_modules/liquidjs": {
- "version": "10.25.0",
- "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.25.0.tgz",
- "integrity": "sha512-XpO7AiGULTG4xcTlwkcTI5JreFG7b6esLCLp+aUSh7YuQErJZEoUXre9u9rbdb0057pfWG4l0VursvLd5Q/eAw==",
+ "version": "10.25.5",
+ "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.25.5.tgz",
+ "integrity": "sha512-GKiKeZjJDdVoQAu+S9rzkYsYnYhcep5W3WwZXgb5f+yq484P/k9JqamBbGYu+LBEixcUAXZr2jogdAIjB3ki1w==",
"license": "MIT",
"dependencies": {
"commander": "^10.0.0"
From 268c33bc17cfefb6efc77a486d295be8dafd841e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 15 Apr 2026 13:55:15 +0330
Subject: [PATCH 11/16] Bump actions/upload-pages-artifact (#437)
Bumps the github-actions-dependencies group with 1 update: [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact).
Updates `actions/upload-pages-artifact` from 4.0.0 to 5.0.0
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/7b1f4a764d45c48632c6b24a0339c27f5614fb0b...fc324d3547104276b827a68afc52ff2a11cc49c9)
---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
dependency-version: 5.0.0
dependency-type: direct:production
update-type: version-update:semver-major
dependency-group: github-actions-dependencies
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
.github/workflows/deploy.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 7c4864f..c114c91 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -26,7 +26,7 @@ jobs:
npm install
npm run build
- name: Upload artifact
- uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: "_site" # The directory that contains the deployable files
- name: Deploy to GitHub Pages
From 6d33863229181144e71a9eb1a2eb6bd691aae4cf Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 15 Apr 2026 21:28:25 +1000
Subject: [PATCH 12/16] Bump the npm-dependencies group across 1 directory with
2 updates (#438)
Bumps the npm-dependencies group with 2 updates in the / directory: [postcss](https://github.com/postcss/postcss) and [esbuild](https://github.com/evanw/esbuild).
Updates `postcss` from 8.5.8 to 8.5.9
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.8...8.5.9)
Updates `esbuild` from 0.27.4 to 0.28.0
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.27.4...v0.28.0)
---
updated-dependencies:
- dependency-name: postcss
dependency-version: 8.5.9
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: npm-dependencies
- dependency-name: esbuild
dependency-version: 0.28.0
dependency-type: direct:development
update-type: version-update:semver-minor
dependency-group: npm-dependencies
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
package-lock.json | 224 +++++++++++++++++++++++-----------------------
package.json | 4 +-
2 files changed, 114 insertions(+), 114 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 7c9099d..8ab3fe7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,13 +25,13 @@
"phaser": "^3.90.0",
"picocolors": "^1.1.1",
"picomatch": "^4.0.4",
- "postcss": "^8.4.45",
+ "postcss": "^8.5.9",
"source-map-js": "^1.2.1",
"tailwindcss": "^4.2.2",
"tapable": "^2.3.2"
},
"devDependencies": {
- "esbuild": "^0.27.4",
+ "esbuild": "^0.28.0",
"npm-run-all": "^4.1.5",
"postcss-cli": "^11.0.0"
},
@@ -228,9 +228,9 @@
}
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
- "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz",
+ "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==",
"cpu": [
"ppc64"
],
@@ -245,9 +245,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
- "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz",
+ "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==",
"cpu": [
"arm"
],
@@ -262,9 +262,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
- "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz",
+ "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==",
"cpu": [
"arm64"
],
@@ -279,9 +279,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
- "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz",
+ "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==",
"cpu": [
"x64"
],
@@ -296,9 +296,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
- "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz",
+ "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==",
"cpu": [
"arm64"
],
@@ -313,9 +313,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
- "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz",
+ "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==",
"cpu": [
"x64"
],
@@ -330,9 +330,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
- "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz",
+ "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==",
"cpu": [
"arm64"
],
@@ -347,9 +347,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
- "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz",
+ "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==",
"cpu": [
"x64"
],
@@ -364,9 +364,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
- "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz",
+ "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==",
"cpu": [
"arm"
],
@@ -381,9 +381,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
- "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz",
+ "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==",
"cpu": [
"arm64"
],
@@ -398,9 +398,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
- "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz",
+ "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==",
"cpu": [
"ia32"
],
@@ -415,9 +415,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
- "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz",
+ "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==",
"cpu": [
"loong64"
],
@@ -432,9 +432,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
- "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz",
+ "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==",
"cpu": [
"mips64el"
],
@@ -449,9 +449,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
- "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz",
+ "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==",
"cpu": [
"ppc64"
],
@@ -466,9 +466,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
- "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz",
+ "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==",
"cpu": [
"riscv64"
],
@@ -483,9 +483,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
- "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz",
+ "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==",
"cpu": [
"s390x"
],
@@ -500,9 +500,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
- "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz",
+ "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==",
"cpu": [
"x64"
],
@@ -517,9 +517,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
- "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz",
+ "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==",
"cpu": [
"arm64"
],
@@ -534,9 +534,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
- "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz",
+ "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==",
"cpu": [
"x64"
],
@@ -551,9 +551,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
- "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz",
+ "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==",
"cpu": [
"arm64"
],
@@ -568,9 +568,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
- "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz",
+ "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==",
"cpu": [
"x64"
],
@@ -585,9 +585,9 @@
}
},
"node_modules/@esbuild/openharmony-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
- "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz",
+ "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==",
"cpu": [
"arm64"
],
@@ -602,9 +602,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
- "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz",
+ "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==",
"cpu": [
"x64"
],
@@ -619,9 +619,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
- "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz",
+ "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==",
"cpu": [
"arm64"
],
@@ -636,9 +636,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
- "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz",
+ "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==",
"cpu": [
"ia32"
],
@@ -653,9 +653,9 @@
}
},
"node_modules/@esbuild/win32-x64": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
- "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz",
+ "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==",
"cpu": [
"x64"
],
@@ -1885,9 +1885,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.27.4",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
- "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
+ "version": "0.28.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz",
+ "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -1898,32 +1898,32 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.27.4",
- "@esbuild/android-arm": "0.27.4",
- "@esbuild/android-arm64": "0.27.4",
- "@esbuild/android-x64": "0.27.4",
- "@esbuild/darwin-arm64": "0.27.4",
- "@esbuild/darwin-x64": "0.27.4",
- "@esbuild/freebsd-arm64": "0.27.4",
- "@esbuild/freebsd-x64": "0.27.4",
- "@esbuild/linux-arm": "0.27.4",
- "@esbuild/linux-arm64": "0.27.4",
- "@esbuild/linux-ia32": "0.27.4",
- "@esbuild/linux-loong64": "0.27.4",
- "@esbuild/linux-mips64el": "0.27.4",
- "@esbuild/linux-ppc64": "0.27.4",
- "@esbuild/linux-riscv64": "0.27.4",
- "@esbuild/linux-s390x": "0.27.4",
- "@esbuild/linux-x64": "0.27.4",
- "@esbuild/netbsd-arm64": "0.27.4",
- "@esbuild/netbsd-x64": "0.27.4",
- "@esbuild/openbsd-arm64": "0.27.4",
- "@esbuild/openbsd-x64": "0.27.4",
- "@esbuild/openharmony-arm64": "0.27.4",
- "@esbuild/sunos-x64": "0.27.4",
- "@esbuild/win32-arm64": "0.27.4",
- "@esbuild/win32-ia32": "0.27.4",
- "@esbuild/win32-x64": "0.27.4"
+ "@esbuild/aix-ppc64": "0.28.0",
+ "@esbuild/android-arm": "0.28.0",
+ "@esbuild/android-arm64": "0.28.0",
+ "@esbuild/android-x64": "0.28.0",
+ "@esbuild/darwin-arm64": "0.28.0",
+ "@esbuild/darwin-x64": "0.28.0",
+ "@esbuild/freebsd-arm64": "0.28.0",
+ "@esbuild/freebsd-x64": "0.28.0",
+ "@esbuild/linux-arm": "0.28.0",
+ "@esbuild/linux-arm64": "0.28.0",
+ "@esbuild/linux-ia32": "0.28.0",
+ "@esbuild/linux-loong64": "0.28.0",
+ "@esbuild/linux-mips64el": "0.28.0",
+ "@esbuild/linux-ppc64": "0.28.0",
+ "@esbuild/linux-riscv64": "0.28.0",
+ "@esbuild/linux-s390x": "0.28.0",
+ "@esbuild/linux-x64": "0.28.0",
+ "@esbuild/netbsd-arm64": "0.28.0",
+ "@esbuild/netbsd-x64": "0.28.0",
+ "@esbuild/openbsd-arm64": "0.28.0",
+ "@esbuild/openbsd-x64": "0.28.0",
+ "@esbuild/openharmony-arm64": "0.28.0",
+ "@esbuild/sunos-x64": "0.28.0",
+ "@esbuild/win32-arm64": "0.28.0",
+ "@esbuild/win32-ia32": "0.28.0",
+ "@esbuild/win32-x64": "0.28.0"
}
},
"node_modules/escalade": {
@@ -3919,9 +3919,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.8",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
- "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "version": "8.5.9",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz",
+ "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==",
"funding": [
{
"type": "opencollective",
diff --git a/package.json b/package.json
index 08f1d65..8c541ff 100644
--- a/package.json
+++ b/package.json
@@ -20,13 +20,13 @@
"phaser": "^3.90.0",
"picocolors": "^1.1.1",
"picomatch": "^4.0.4",
- "postcss": "^8.4.45",
+ "postcss": "^8.5.9",
"source-map-js": "^1.2.1",
"tailwindcss": "^4.2.2",
"tapable": "^2.3.2"
},
"devDependencies": {
- "esbuild": "^0.27.4",
+ "esbuild": "^0.28.0",
"npm-run-all": "^4.1.5",
"postcss-cli": "^11.0.0"
},
From 7e6f931fc71a716ca3c3eedc664cded46709697c Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 16:17:28 +1000
Subject: [PATCH 13/16] Remove pre-start animations for Space Invaders (#439)
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/7a2c3d4c-134f-4fb6-aeaa-9161764680a3
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
src/assets/js/eggs.js | 13 +----
src/assets/js/games/space-invaders.js | 84 +--------------------------
2 files changed, 3 insertions(+), 94 deletions(-)
diff --git a/src/assets/js/eggs.js b/src/assets/js/eggs.js
index 326f8ab..1bb3021 100644
--- a/src/assets/js/eggs.js
+++ b/src/assets/js/eggs.js
@@ -22,21 +22,10 @@
heartClickCount++;
- // Visual feedback: heart grows with each click
- const scaleAmount = 1 + heartClickCount * 0.3;
- heart.style.transition =
- "transform 0.1s cubic-bezier(0.17, 0.67, 0.83, 0.67)";
- heart.style.transform = `scale(${scaleAmount})`;
-
if (heartClickCount === 5) {
phaserStarted = true;
heart.innerHTML = "đŽ";
- heart.style.transform = "scale(1.5)";
-
- setTimeout(() => {
- heart.style.opacity = "0";
- SpaceInvaders.launch();
- }, 300);
+ SpaceInvaders.launch();
}
});
})();
diff --git a/src/assets/js/games/space-invaders.js b/src/assets/js/games/space-invaders.js
index 2c8a273..980248a 100644
--- a/src/assets/js/games/space-invaders.js
+++ b/src/assets/js/games/space-invaders.js
@@ -9,41 +9,6 @@
*/
const SpaceInvaders = (() => {
- // âââ Emoji assets ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
-
- const BURST_EMOJIS = [
- "đŽ",
- "đšī¸",
- "đž",
- "đ",
- "â¨",
- "â",
- "đĨ",
- "đĨ",
- "đ",
- "đ",
- "đ",
- "đ",
- "đ¤",
- "đģ",
- "đĻ",
- "đ",
- "đ",
- "âĄ",
- "đ",
- "đ¯",
- "đ¸",
- "đŊ",
- "đž",
- "đ",
- "đĻ",
- "đĒ",
- "đ",
- "đ ",
- "âī¸",
- "đ",
- ];
-
const ALIEN_ROWS = ["đž", "đŊ", "đ¸", "đ", "đž"];
const GAME_ID = "space-invaders";
@@ -70,7 +35,7 @@ const SpaceInvaders = (() => {
width: "100vw",
height: "100vh",
zIndex: "10000",
- pointerEvents: "none", // non-interactive until explosion is done
+ pointerEvents: "auto",
});
document.body.appendChild(canvas);
@@ -97,24 +62,7 @@ const SpaceInvaders = (() => {
// âââ Scene callbacks âââââââââââââââââââââââââââââââââââââââââââââââââââââ
function _onCreate() {
- const particles = _spawnExplosion(this);
-
- // After 5 s, fade out the explosion and start the real game
- this.time.delayedCall(5000, () => {
- this.tweens.add({
- targets: particles.getChildren(),
- alpha: 0,
- duration: 1000,
- onComplete: () => {
- particles.clear(true, true);
-
- const canvas = document.getElementById("game-canvas-" + GAME_ID);
- if (canvas) canvas.style.pointerEvents = "auto";
-
- _setupGame(this);
- },
- });
- });
+ _setupGame(this);
}
function _onUpdate() {
@@ -135,34 +83,6 @@ const SpaceInvaders = (() => {
// âââ Game setup ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
- function _spawnExplosion(scene) {
- const heartEl = document.getElementById("footer-heart");
- const rect = heartEl
- ? heartEl.getBoundingClientRect()
- : { left: window.innerWidth / 2, top: window.innerHeight - 60 };
-
- const group = scene.add.group();
-
- for (let i = 0; i < 40; i++) {
- const emoji = Phaser.Utils.Array.GetRandom(BURST_EMOJIS);
- const p = scene.add.text(rect.left, rect.top, emoji, {
- fontSize: "32px",
- });
-
- scene.physics.add.existing(p);
- p.body.setVelocity(
- Phaser.Math.Between(-400, 400),
- Phaser.Math.Between(-600, -1200),
- );
- p.body.setBounce(0.6);
- p.body.setCollideWorldBounds(true);
- p.body.setAngularVelocity(Phaser.Math.Between(-200, 200));
- group.add(p);
- }
-
- return group;
- }
-
function _setupGame(scene) {
// Player rocket
scene.si_player = scene.add.text(
From bf607c7a93811f4f461f5aafc66db71cbc0f3903 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 16:24:47 +1000
Subject: [PATCH 14/16] docs: move contribution and troubleshooting above git
sections in README (#440)
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/dc670618-c087-4324-858b-751c810f0eb4
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Co-authored-by: John Bampton
---
README.md | 230 +++++++++++++++++++++++++++---------------------------
1 file changed, 114 insertions(+), 116 deletions(-)
diff --git a/README.md b/README.md
index 016af0b..115fe63 100644
--- a/README.md
+++ b/README.md
@@ -28,10 +28,10 @@
- [How to Add Yourself](#-how-to-add-yourself)
- [YAML File Format](#-yaml-file-format)
- [Local Development](#-local-development-optional)
-- [Git Workflow & Keeping in Sync](#-git-workflow--keeping-in-sync)
-- [Contributing with GitHub CLI](#-contributing-with-github-cli)
- [Contribution Guidelines](#-contribution-guidelines)
- [Troubleshooting](#-troubleshooting--faq)
+- [Git Workflow & Keeping in Sync](#-git-workflow--keeping-in-sync)
+- [Contributing with GitHub CLI](#-contributing-with-github-cli)
- [License](#-license)
---
@@ -343,6 +343,118 @@ NextCommunity.github.io/
---
+## đ¤ Contribution Guidelines
+
+### Code of Conduct
+
+We're committed to providing a welcoming and inclusive environment. Please be respectful and professional in all interactions.
+
+### PR Review Process
+
+1. **Automated Checks**: Your PR will automatically run linting checks
+2. **Manual Review**: A maintainer will review your submission
+3. **Feedback**: You may be asked to make changes
+4. **Merge**: Once approved, your PR will be merged!
+
+### What Gets Approved?
+
+â
**Yes:**
+
+- Complete, valid YAML files
+- Professional bios and appropriate content
+- Real GitHub profiles
+- Accurate information
+
+â **No:**
+
+- Spam or promotional content
+- Offensive or inappropriate material
+- Fake or duplicate profiles
+- Invalid YAML syntax
+
+### CI/CD Checks
+
+Every pull request runs automated checks:
+
+- **Linting**: Ensures YAML syntax is correct
+- **Build Test**: Verifies the site builds successfully
+- **Pre-commit Hooks**: Checks code quality
+
+If checks fail, you'll see error messages in the PR. Fix the issues and push again.
+
+---
+
+## đ§ Troubleshooting & FAQ
+
+### Common Issues
+
+#### â Build Fails: "Invalid YAML"
+
+**Problem**: Your YAML file has syntax errors.
+
+**Solution**:
+
+- Check for proper indentation (use spaces, not tabs)
+- Ensure colons have a space after them (`name: John`, not `name:John`)
+- Use `|` for multi-line bio text
+- Validate your YAML at [yamllint.com](http://www.yamllint.com/)
+
+#### â "GitHub username not found"
+
+**Problem**: The `github` field doesn't match a real GitHub profile.
+
+**Solution**:
+
+- Ensure you're using your exact GitHub username
+- Check for typos
+- Username is case-sensitive in this field
+
+#### â My profile doesn't show up
+
+**Problem**: File naming or format issue.
+
+**Solution**:
+
+- File must be in `src/users/` directory
+- File must be named `username.yaml` (lowercase, with `.yaml` extension)
+- All required fields must be filled in
+
+#### â Pre-commit hooks fail
+
+**Problem**: Code quality checks didn't pass.
+
+**Solution**:
+
+```bash
+# Install pre-commit
+pip install pre-commit
+
+# Run checks manually
+pre-commit run --all-files
+```
+
+### FAQ
+
+**Q: Can I update my profile after it's merged?**
+A: Yes! Just create a new PR with updates to your YAML file.
+
+**Q: How long does review take?**
+A: Usually within 24-48 hours, depending on maintainer availability.
+
+**Q: Can I add multiple social links?**
+A: Yes, all social fields (twitter, linkedin, instagram) are optional and independent.
+
+**Q: What if I don't have a personal website?**
+A: No problem! Just omit the `website` field or set it to your GitHub profile.
+
+**Q: Can I use emojis in my profile?**
+A: Yes, emojis are supported in the `name` and `bio` fields! đ
+
+**Q: Is there a character limit for the bio?**
+A: No hard limit, but keep it concise (2-4 paragraphs recommended).
+
+---
+
## đ Git Workflow & Keeping in Sync
Working with a forked repository means your copy can fall behind the upstream (the original NextCommunity repo) over time. This section explains the complete feature-branch workflow and the essential git commands every contributor should know.
@@ -644,120 +756,6 @@ git push origin add-your-github-username
Once all checks pass and a maintainer approves the PR, it will be merged and your profile will go live! đ
----
-
-## đ¤ Contribution Guidelines
-
-### Code of Conduct
-
-We're committed to providing a welcoming and inclusive environment. Please be respectful and professional in all interactions.
-
-### PR Review Process
-
-1. **Automated Checks**: Your PR will automatically run linting checks
-2. **Manual Review**: A maintainer will review your submission
-3. **Feedback**: You may be asked to make changes
-4. **Merge**: Once approved, your PR will be merged!
-
-### What Gets Approved?
-
-â
**Yes:**
-
-- Complete, valid YAML files
-- Professional bios and appropriate content
-- Real GitHub profiles
-- Accurate information
-
-â **No:**
-
-- Spam or promotional content
-- Offensive or inappropriate material
-- Fake or duplicate profiles
-- Invalid YAML syntax
-
-### CI/CD Checks
-
-Every pull request runs automated checks:
-
-- **Linting**: Ensures YAML syntax is correct
-- **Build Test**: Verifies the site builds successfully
-- **Pre-commit Hooks**: Checks code quality
-
-If checks fail, you'll see error messages in the PR. Fix the issues and push again.
-
----
-
-## đ§ Troubleshooting & FAQ
-
-### Common Issues
-
-#### â Build Fails: "Invalid YAML"
-
-**Problem**: Your YAML file has syntax errors.
-
-**Solution**:
-
-- Check for proper indentation (use spaces, not tabs)
-- Ensure colons have a space after them (`name: John`, not `name:John`)
-- Use `|` for multi-line bio text
-- Validate your YAML at [yamllint.com](http://www.yamllint.com/)
-
-#### â "GitHub username not found"
-
-**Problem**: The `github` field doesn't match a real GitHub profile.
-
-**Solution**:
-
-- Ensure you're using your exact GitHub username
-- Check for typos
-- Username is case-sensitive in this field
-
-#### â My profile doesn't show up
-
-**Problem**: File naming or format issue.
-
-**Solution**:
-
-- File must be in `src/users/` directory
-- File must be named `username.yaml` (lowercase, with `.yaml` extension)
-- All required fields must be filled in
-
-#### â Pre-commit hooks fail
-
-**Problem**: Code quality checks didn't pass.
-
-**Solution**:
-
-```bash
-# Install pre-commit
-pip install pre-commit
-
-# Run checks manually
-pre-commit run --all-files
-```
-
-### FAQ
-
-**Q: Can I update my profile after it's merged?**
-A: Yes! Just create a new PR with updates to your YAML file.
-
-**Q: How long does review take?**
-A: Usually within 24-48 hours, depending on maintainer availability.
-
-**Q: Can I add multiple social links?**
-A: Yes, all social fields (twitter, linkedin, instagram) are optional and independent.
-
-**Q: What if I don't have a personal website?**
-A: No problem! Just omit the `website` field or set it to your GitHub profile.
-
-**Q: Can I use emojis in my profile?**
-A: Yes, emojis are supported in the `name` and `bio` fields! đ
-
-**Q: Is there a character limit for the bio?**
-A: No hard limit, but keep it concise (2-4 paragraphs recommended).
-
----
-
## đ License
This project is licensed under the **GNU General Public License v3.0** - see the [LICENSE](LICENSE) file for details.
From bddb285e7c2e5bf388ba9c66690639cb950acf98 Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 16:35:49 +1000
Subject: [PATCH 15/16] Space Invaders: reclaim off-screen bullets, enforce
black playfield, preserve ESC exit (#441)
* Space Invaders: cleanup offscreen bullets and black canvas background
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/4a92f727-d408-427a-8bee-fc96696e3d01
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
* Space Invaders: extract bullet cleanup buffer constant
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/4a92f727-d408-427a-8bee-fc96696e3d01
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
Co-authored-by: John Bampton
---
src/assets/js/games/space-invaders.js | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/assets/js/games/space-invaders.js b/src/assets/js/games/space-invaders.js
index 980248a..1f09de4 100644
--- a/src/assets/js/games/space-invaders.js
+++ b/src/assets/js/games/space-invaders.js
@@ -11,6 +11,7 @@
const SpaceInvaders = (() => {
const ALIEN_ROWS = ["đž", "đŊ", "đ¸", "đ", "đž"];
const GAME_ID = "space-invaders";
+ const BULLET_CLEANUP_BUFFER = 40;
// âââ Public entry-point ââââââââââââââââââââââââââââââââââââââââââââââââââ
@@ -36,6 +37,7 @@ const SpaceInvaders = (() => {
height: "100vh",
zIndex: "10000",
pointerEvents: "auto",
+ background: "#000000",
});
document.body.appendChild(canvas);
@@ -44,7 +46,8 @@ const SpaceInvaders = (() => {
canvas: canvas,
width: window.innerWidth,
height: window.innerHeight,
- transparent: true,
+ transparent: false,
+ backgroundColor: "#000000",
physics: {
default: "arcade",
arcade: { gravity: { y: 0 }, debug: false },
@@ -79,6 +82,18 @@ const SpaceInvaders = (() => {
if (this.si_cursors.space.isDown) {
_fireBullet(this);
}
+
+ const bullets = this.si_bullets?.getChildren?.() || [];
+ bullets.forEach((bullet) => {
+ if (!bullet.active) return;
+ if (
+ bullet.y < -BULLET_CLEANUP_BUFFER ||
+ bullet.x < -BULLET_CLEANUP_BUFFER ||
+ bullet.x > this.scale.width + BULLET_CLEANUP_BUFFER
+ ) {
+ bullet.destroy();
+ }
+ });
}
// âââ Game setup ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
From 268e39b4eb602f3cee419306b4d362ade8ec9a4c Mon Sep 17 00:00:00 2001
From: Copilot <198982749+Copilot@users.noreply.github.com>
Date: Sun, 19 Apr 2026 16:46:42 +1000
Subject: [PATCH 16/16] Add invader-hit SFX on bullet collisions in Space
Invaders (#443)
* Add hit sound when Space Invaders bullet destroys an invader
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/2e21a107-94cf-4f0c-8d3f-8dae8d66ef0b
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
* Clean up Web Audio nodes after invader hit sound
Agent-Logs-Url: https://github.com/NextCommunity/NextCommunity.github.io/sessions/2e21a107-94cf-4f0c-8d3f-8dae8d66ef0b
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jbampton <418747+jbampton@users.noreply.github.com>
---
src/assets/js/games/space-invaders.js | 36 +++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/src/assets/js/games/space-invaders.js b/src/assets/js/games/space-invaders.js
index 1f09de4..1956d70 100644
--- a/src/assets/js/games/space-invaders.js
+++ b/src/assets/js/games/space-invaders.js
@@ -12,6 +12,7 @@ const SpaceInvaders = (() => {
const ALIEN_ROWS = ["đž", "đŊ", "đ¸", "đ", "đž"];
const GAME_ID = "space-invaders";
const BULLET_CLEANUP_BUFFER = 40;
+ let _audioContext = null;
// âââ Public entry-point ââââââââââââââââââââââââââââââââââââââââââââââââââ
@@ -152,6 +153,7 @@ const SpaceInvaders = (() => {
(bullet, alien) => {
bullet.destroy();
alien.destroy();
+ _playInvaderHitSound();
if (scene.si_aliens.countActive() === 0) {
_onVictory(scene);
@@ -224,6 +226,40 @@ const SpaceInvaders = (() => {
scene.si_lastFired = now;
}
+ function _playInvaderHitSound() {
+ const AudioCtx = window.AudioContext || window.webkitAudioContext;
+ if (!AudioCtx) return;
+
+ if (!_audioContext) {
+ _audioContext = new AudioCtx();
+ }
+ if (_audioContext.state === "suspended") {
+ _audioContext.resume().catch(() => {});
+ }
+
+ const now = _audioContext.currentTime;
+ const oscillator = _audioContext.createOscillator();
+ const gainNode = _audioContext.createGain();
+
+ oscillator.type = "square";
+ oscillator.frequency.setValueAtTime(840, now);
+ oscillator.frequency.exponentialRampToValueAtTime(280, now + 0.08);
+
+ gainNode.gain.setValueAtTime(0.0001, now);
+ gainNode.gain.exponentialRampToValueAtTime(0.12, now + 0.01);
+ gainNode.gain.exponentialRampToValueAtTime(0.0001, now + 0.09);
+
+ oscillator.connect(gainNode);
+ gainNode.connect(_audioContext.destination);
+ oscillator.onended = () => {
+ oscillator.disconnect();
+ gainNode.disconnect();
+ };
+
+ oscillator.start(now);
+ oscillator.stop(now + 0.1);
+ }
+
// âââ Victory / cleanup ââââââââââââââââââââââââââââââââââââââââââââââââââââ
function _onVictory(scene) {