create-template-html-css 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +305 -0
  2. package/HTML-VS-REACT.md +289 -0
  3. package/QUICKSTART-REACT.md +293 -0
  4. package/REACT-SUPPORT-SUMMARY.md +235 -0
  5. package/README.md +193 -12
  6. package/bin/cli.js +98 -759
  7. package/bin/commands/create.js +272 -0
  8. package/bin/commands/gallery.js +42 -0
  9. package/bin/commands/insert.js +123 -0
  10. package/bin/commands/list.js +73 -0
  11. package/package.json +10 -3
  12. package/src/component-choices.js +7 -0
  13. package/src/components-registry.js +112 -0
  14. package/src/format-utils.js +49 -0
  15. package/src/generator.js +83 -594
  16. package/src/generators/color-schemes.js +78 -0
  17. package/src/generators/color-utils.js +108 -0
  18. package/src/generators/component-filters.js +151 -0
  19. package/src/generators/html-generators.js +180 -0
  20. package/src/generators/validation.js +43 -0
  21. package/src/index.js +2 -1
  22. package/src/inserter.js +55 -233
  23. package/src/inserters/backup-utils.js +20 -0
  24. package/src/inserters/component-loader.js +68 -0
  25. package/src/inserters/html-utils.js +31 -0
  26. package/src/inserters/indentation-utils.js +90 -0
  27. package/src/inserters/validation-utils.js +49 -0
  28. package/src/react-component-choices.js +45 -0
  29. package/src/react-file-operations.js +172 -0
  30. package/src/react-generator.js +208 -0
  31. package/src/react-templates.js +350 -0
  32. package/src/utils/file-utils.js +97 -0
  33. package/src/utils/path-utils.js +32 -0
  34. package/src/utils/string-utils.js +51 -0
  35. package/src/utils/template-loader.js +91 -0
  36. package/templates/_shared/PATTERNS.md +246 -0
  37. package/templates/_shared/README.md +74 -0
  38. package/templates/_shared/base.css +18 -0
  39. package/templates/blackjack/index.html +1 -1
  40. package/templates/blackjack/script.js +9 -9
  41. package/templates/breakout/index.html +1 -1
  42. package/templates/breakout/script.js +6 -6
  43. package/templates/connect-four/index.html +1 -1
  44. package/templates/connect-four/script.js +5 -5
  45. package/templates/dice-game/index.html +1 -1
  46. package/templates/dice-game/script.js +20 -20
  47. package/templates/flappy-bird/index.html +1 -1
  48. package/templates/flappy-bird/script.js +10 -10
  49. package/templates/pong/index.html +1 -1
  50. package/templates/pong/script.js +8 -8
  51. package/templates/skeleton/index.html +4 -4
  52. package/templates/slot-machine/index.html +1 -1
  53. package/templates/slot-machine/script.js +6 -6
  54. package/templates/tetris/index.html +1 -1
  55. package/templates/tetris/script.js +5 -5
  56. package/templates-react/README.md +126 -0
  57. package/templates-react/button/Button.css +88 -0
  58. package/templates-react/button/Button.example.jsx +40 -0
  59. package/templates-react/button/Button.jsx +29 -0
  60. package/templates-react/card/Card.css +86 -0
  61. package/templates-react/card/Card.example.jsx +49 -0
  62. package/templates-react/card/Card.jsx +35 -0
  63. package/templates-react/counter/Counter.css +99 -0
  64. package/templates-react/counter/Counter.example.jsx +45 -0
  65. package/templates-react/counter/Counter.jsx +70 -0
  66. package/templates-react/form/Form.css +128 -0
  67. package/templates-react/form/Form.example.jsx +65 -0
  68. package/templates-react/form/Form.jsx +125 -0
  69. package/templates-react/modal/Modal.css +152 -0
  70. package/templates-react/modal/Modal.example.jsx +90 -0
  71. package/templates-react/modal/Modal.jsx +46 -0
  72. package/templates-react/todo-list/TodoList.css +236 -0
  73. package/templates-react/todo-list/TodoList.example.jsx +15 -0
  74. package/templates-react/todo-list/TodoList.jsx +84 -0
@@ -0,0 +1,246 @@
1
+ # Template Code Patterns
2
+
3
+ This document catalogs common code patterns found across templates. These patterns are intentionally duplicated in each template to maintain independence.
4
+
5
+ ## JavaScript Patterns
6
+
7
+ ### DOM Selection Patterns
8
+
9
+ **querySelector/querySelectorAll** - Used in 40+ templates
10
+ ```javascript
11
+ const element = document.querySelector('.class-name');
12
+ const elements = document.querySelectorAll('.multiple-items');
13
+ ```
14
+
15
+ **getElementById** - Used in 35+ templates (especially games and interactive components)
16
+ ```javascript
17
+ const button = document.getElementById('myButton');
18
+ ```
19
+
20
+ ### Event Listener Patterns
21
+
22
+ **Click Handlers** - Found in all interactive templates
23
+ ```javascript
24
+ button.addEventListener('click', handleClick);
25
+
26
+ // Or inline
27
+ button.addEventListener('click', () => {
28
+ // Handle click
29
+ });
30
+ ```
31
+
32
+ **Common Event Setup**
33
+ ```javascript
34
+ // Multiple elements
35
+ buttons.forEach(button => {
36
+ button.addEventListener('click', handler);
37
+ });
38
+
39
+ // Delegation pattern
40
+ document.addEventListener('click', function(e) {
41
+ if (e.target.matches('.selector')) {
42
+ // Handle
43
+ }
44
+ });
45
+ ```
46
+
47
+ ### Game Control Patterns
48
+
49
+ Found in 12 game templates (snake, tetris, pong, etc.):
50
+ ```javascript
51
+ let gameActive = false;
52
+ let score = 0;
53
+
54
+ function startGame() {
55
+ gameActive = true;
56
+ score = 0;
57
+ // Initialize game
58
+ }
59
+
60
+ function pauseGame() {
61
+ gameActive = false;
62
+ // Pause logic
63
+ }
64
+
65
+ function resetGame() {
66
+ gameActive = false;
67
+ score = 0;
68
+ // Reset logic
69
+ }
70
+
71
+ // Button bindings
72
+ startBtn.addEventListener('click', startGame);
73
+ pauseBtn.addEventListener('click', pauseGame);
74
+ resetBtn.addEventListener('click', resetGame);
75
+ ```
76
+
77
+ ### Update Display Pattern
78
+
79
+ Common in counters, scores, and dynamic content:
80
+ ```javascript
81
+ function updateDisplay() {
82
+ element.textContent = value;
83
+ // Update other UI elements
84
+ }
85
+ ```
86
+
87
+ ## CSS Patterns
88
+
89
+ ### Layout Patterns
90
+
91
+ **Centered Container** (30+ templates)
92
+ ```css
93
+ body {
94
+ display: flex;
95
+ justify-content: center;
96
+ align-items: center;
97
+ min-height: 100vh;
98
+ }
99
+
100
+ .container {
101
+ background: white;
102
+ padding: 40px;
103
+ border-radius: 15px;
104
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
105
+ }
106
+ ```
107
+
108
+ **Grid Layout** (15+ templates)
109
+ ```css
110
+ .grid {
111
+ display: grid;
112
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
113
+ gap: 20px;
114
+ }
115
+ ```
116
+
117
+ **Flexbox Layout** (20+ templates)
118
+ ```css
119
+ .flex-container {
120
+ display: flex;
121
+ gap: 15px;
122
+ flex-wrap: wrap;
123
+ }
124
+ ```
125
+
126
+ ### Animation Patterns
127
+
128
+ **Hover Transitions** (35+ templates)
129
+ ```css
130
+ .element {
131
+ transition: all 0.3s ease;
132
+ }
133
+
134
+ .element:hover {
135
+ transform: translateY(-5px);
136
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
137
+ }
138
+ ```
139
+
140
+ **Fade Animations**
141
+ ```css
142
+ @keyframes fadeIn {
143
+ from { opacity: 0; }
144
+ to { opacity: 1; }
145
+ }
146
+
147
+ .animated {
148
+ animation: fadeIn 0.5s ease-in-out;
149
+ }
150
+ ```
151
+
152
+ ### Button Patterns
153
+
154
+ Found in 40+ templates:
155
+ ```css
156
+ .btn {
157
+ padding: 12px 24px;
158
+ border: none;
159
+ border-radius: 8px;
160
+ cursor: pointer;
161
+ font-size: 16px;
162
+ transition: all 0.3s ease;
163
+ }
164
+
165
+ .btn:hover {
166
+ transform: translateY(-2px);
167
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
168
+ }
169
+
170
+ .btn:active {
171
+ transform: translateY(0);
172
+ }
173
+ ```
174
+
175
+ ## HTML Patterns
176
+
177
+ ### Semantic Structure
178
+
179
+ **Container → Card → Content** (25+ templates)
180
+ ```html
181
+ <div class="container">
182
+ <div class="card">
183
+ <h1>Title</h1>
184
+ <p>Content</p>
185
+ </div>
186
+ </div>
187
+ ```
188
+
189
+ **Form Structure** (form, login, register templates)
190
+ ```html
191
+ <form class="form">
192
+ <h1 class="form-title">Title</h1>
193
+ <div class="form-group">
194
+ <label for="input">Label</label>
195
+ <input type="text" id="input" name="input">
196
+ </div>
197
+ <button type="submit">Submit</button>
198
+ </form>
199
+ ```
200
+
201
+ ### Canvas for Games (10 game templates)
202
+ ```html
203
+ <canvas id="gameCanvas" width="400" height="400"></canvas>
204
+ <div class="game-controls">
205
+ <button id="startBtn">Start</button>
206
+ <button id="pauseBtn">Pause</button>
207
+ <button id="resetBtn">Reset</button>
208
+ </div>
209
+ ```
210
+
211
+ ## Why These Patterns Repeat
212
+
213
+ 1. **Consistency**: Users recognize familiar patterns across templates
214
+ 2. **Learning**: Patterns reinforce best practices
215
+ 3. **Copy-Paste Ready**: Each template works standalone
216
+ 4. **No Dependencies**: No shared libraries to break
217
+
218
+ ## Best Practices for New Templates
219
+
220
+ When creating new templates, follow these patterns:
221
+
222
+ ✅ **DO**:
223
+ - Use semantic HTML5 elements
224
+ - Include comprehensive comments
225
+ - Follow existing naming conventions
226
+ - Keep JavaScript vanilla (no frameworks)
227
+ - Make it work without any build process
228
+
229
+ ❌ **DON'T**:
230
+ - Import from other templates
231
+ - Require external libraries (unless clearly documented)
232
+ - Use complex build tools
233
+ - Break the self-contained principle
234
+
235
+ ## Statistics
236
+
237
+ - **Total Templates**: 42
238
+ - **JavaScript Files**: 42
239
+ - **CSS Files**: 42
240
+ - **HTML Files**: 42
241
+ - **Average File Size**: ~150 lines per file
242
+ - **Common Patterns**: 15+ recurring patterns across templates
243
+
244
+ ---
245
+
246
+ *These patterns ensure consistency while maintaining template independence.*
@@ -0,0 +1,74 @@
1
+ # Shared Template Resources
2
+
3
+ This directory contains shared resources and documentation for templates.
4
+
5
+ ## Philosophy: Self-Contained Templates
6
+
7
+ **Each template is intentionally self-contained and standalone.** This means:
8
+ - ✅ Every template includes its own complete HTML, CSS, and JS
9
+ - ✅ No external dependencies between templates
10
+ - ✅ Users can copy a single template folder and it "just works"
11
+ - ✅ Perfect for learning, prototyping, and quick integration
12
+
13
+ ## Why Not Use Shared CSS?
14
+
15
+ While we have `base.css` with common styles, **we deliberately duplicate** them in each template because:
16
+
17
+ 1. **Portability**: Users can grab one folder and go
18
+ 2. **Independence**: No broken links if files are moved
19
+ 3. **Customization**: Users can modify without affecting others
20
+ 4. **Simplicity**: No build process or import management needed
21
+
22
+ ## Common Patterns (For Reference)
23
+
24
+ ### CSS Reset (42/42 templates)
25
+ ```css
26
+ * {
27
+ margin: 0;
28
+ padding: 0;
29
+ box-sizing: border-box;
30
+ }
31
+ ```
32
+
33
+ ### Gradient Body (37/42 templates)
34
+ ```css
35
+ body {
36
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
37
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
38
+ min-height: 100vh;
39
+ }
40
+ ```
41
+
42
+ ### Common Container Pattern
43
+ ```css
44
+ .container {
45
+ background: white;
46
+ padding: 40px;
47
+ border-radius: 15px;
48
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
49
+ }
50
+ ```
51
+
52
+ ## Files
53
+
54
+ ### base.css
55
+ Reference implementation of common CSS patterns. Use this as a template when creating new components.
56
+
57
+ ## Creating New Templates
58
+
59
+ When adding new templates:
60
+ 1. Copy the full CSS reset and base styles (don't import)
61
+ 2. Follow existing naming conventions
62
+ 3. Keep it self-contained
63
+ 4. Test that the folder works in isolation
64
+
65
+ ## Statistics
66
+
67
+ - **Total Templates**: 42
68
+ - **Templates with CSS Reset**: 42 (100%)
69
+ - **Templates with Gradient Background**: 37 (88%)
70
+ - **Duplication is intentional** for better user experience
71
+
72
+ ---
73
+
74
+ *Note: This duplication is a feature, not a bug. It optimizes for end-user experience over DRY principles.*
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Shared CSS Reset and Base Styles
3
+ * This file contains common styles used across all templates
4
+ */
5
+
6
+ /* CSS Reset */
7
+ * {
8
+ margin: 0;
9
+ padding: 0;
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ /* Base Body Styles - Common gradient background and font */
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ }
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Blackjack - 21</title>
6
+ <title>{{name}} - Blackjack Game</title>
7
7
  <link rel="stylesheet" href="style.css">
8
8
  </head>
9
9
  <body>
@@ -156,7 +156,7 @@ document.querySelectorAll('.bet-btn').forEach(btn => {
156
156
  updateDisplay();
157
157
  document.getElementById('dealBtn').disabled = false;
158
158
  } else {
159
- showMessage('אין מספיק קרדיטים!', 'error');
159
+ showMessage('Not enough credits!', 'error');
160
160
  }
161
161
  });
162
162
  });
@@ -166,7 +166,7 @@ document.getElementById('dealBtn').addEventListener('click', startGame);
166
166
 
167
167
  function startGame() {
168
168
  if (gameState.currentBet === 0) {
169
- showMessage('בחר הימור תחילה!', 'error');
169
+ showMessage('Choose a bet first!', 'error');
170
170
  return;
171
171
  }
172
172
 
@@ -261,7 +261,7 @@ document.getElementById('doubleBtn').addEventListener('click', () => {
261
261
  stand();
262
262
  }
263
263
  } else {
264
- showMessage('אין מספיק קרדיטים להכפלה!', 'error');
264
+ showMessage('Not enough credits to double down!', 'error');
265
265
  }
266
266
  });
267
267
 
@@ -301,23 +301,23 @@ function endGame(result) {
301
301
  switch (result) {
302
302
  case 'blackjack':
303
303
  winAmount = Math.floor(gameState.currentBet * 2.5); // 3:2 payout
304
- message = '🎉 BLACKJACK! אתה מנצח!';
304
+ message = '🎉 BLACKJACK! You win!';
305
305
  gameState.wins++;
306
306
  break;
307
307
  case 'win':
308
308
  winAmount = gameState.currentBet * 2;
309
- message = '🎉 ניצחת!';
309
+ message = '🎉 You won!';
310
310
  gameState.wins++;
311
311
  break;
312
312
  case 'lose':
313
- message = '😢 הפסדת!';
313
+ message = '😢 You lost!';
314
314
  break;
315
315
  case 'push':
316
316
  winAmount = gameState.currentBet;
317
- message = '🤝 תיקו!';
317
+ message = '🤝 Push!';
318
318
  break;
319
319
  case 'bust':
320
- message = '💥 עברת את 21! הפסדת!';
320
+ message = '💥 Busted! You lost!';
321
321
  break;
322
322
  }
323
323
 
@@ -337,7 +337,7 @@ function endGame(result) {
337
337
  // Check if out of credits
338
338
  if (gameState.credits < 10) {
339
339
  setTimeout(() => {
340
- alert('נגמרו הקרדיטים! מקבל 1000 קרדיטים חדשים.');
340
+ alert('Out of credits! Receiving 1000 new credits.');
341
341
  gameState.credits = 1000;
342
342
  updateDisplay();
343
343
  saveGame();
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Breakout</title>
6
+ <title>{{name}} - Breakout Game</title>
7
7
  <link rel="stylesheet" href="style.css">
8
8
  </head>
9
9
  <body>
@@ -263,11 +263,11 @@ function gameOver() {
263
263
  ctx.fillStyle = '#FFFFFF';
264
264
  ctx.font = 'bold 48px Arial';
265
265
  ctx.textAlign = 'center';
266
- ctx.fillText('משחק נגמר!', canvas.width / 2, canvas.height / 2 - 40);
266
+ ctx.fillText('Game Over!', canvas.width / 2, canvas.height / 2 - 40);
267
267
 
268
268
  ctx.font = '24px Arial';
269
- ctx.fillText(`ניקוד סופי: ${gameState.score}`, canvas.width / 2, canvas.height / 2 + 20);
270
- ctx.fillText('לחץ "אתחל" להתחיל מחדש', canvas.width / 2, canvas.height / 2 + 60);
269
+ ctx.fillText(`Final Score: ${gameState.score}`, canvas.width / 2, canvas.height / 2 + 20);
270
+ ctx.fillText('Click "Reset" to restart', canvas.width / 2, canvas.height / 2 + 60);
271
271
 
272
272
  document.getElementById('startBtn').disabled = false;
273
273
  document.getElementById('pauseBtn').disabled = true;
@@ -306,7 +306,7 @@ function draw() {
306
306
  ctx.fillStyle = '#FFFFFF';
307
307
  ctx.font = 'bold 36px Arial';
308
308
  ctx.textAlign = 'center';
309
- ctx.fillText('משחק מושהה', canvas.width / 2, canvas.height / 2);
309
+ ctx.fillText('Game Paused', canvas.width / 2, canvas.height / 2);
310
310
  }
311
311
  }
312
312
 
@@ -349,7 +349,7 @@ function startGame() {
349
349
  // Pause game
350
350
  function pauseGame() {
351
351
  gameState.paused = !gameState.paused;
352
- document.getElementById('pauseBtn').textContent = gameState.paused ? 'המשך' : 'השהה';
352
+ document.getElementById('pauseBtn').textContent = gameState.paused ? 'Resume' : 'Pause';
353
353
  }
354
354
 
355
355
  // Reset game
@@ -372,7 +372,7 @@ function resetGame() {
372
372
 
373
373
  document.getElementById('startBtn').disabled = false;
374
374
  document.getElementById('pauseBtn').disabled = true;
375
- document.getElementById('pauseBtn').textContent = 'השהה';
375
+ document.getElementById('pauseBtn').textContent = 'Pause';
376
376
  }
377
377
 
378
378
  // Event listeners
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Connect Four</title>
6
+ <title>{{name}} - Connect Four Game</title>
7
7
  <link rel="stylesheet" href="style.css">
8
8
  </head>
9
9
  <body>
@@ -331,15 +331,15 @@ function endGame(winner) {
331
331
  gameState.score1++;
332
332
  localStorage.setItem('connect4Score1', gameState.score1);
333
333
  updateScore();
334
- showMessage('🎉 שחקן 1 ניצח!', 'player1');
334
+ showMessage('🎉 Player 1 wins!', 'player1');
335
335
  } else if (winner === PLAYER2) {
336
336
  gameState.score2++;
337
337
  localStorage.setItem('connect4Score2', gameState.score2);
338
338
  updateScore();
339
- const message = gameState.gameMode === 'pvc' ? '🤖 המחשב ניצח!' : '🎉 שחקן 2 ניצח!';
339
+ const message = gameState.gameMode === 'pvc' ? '🤖 Computer wins!' : '🎉 Player 2 wins!';
340
340
  showMessage(message, 'player2');
341
341
  } else {
342
- showMessage('🤝 תיקו!', 'draw');
342
+ showMessage('🤝 Draw!', 'draw');
343
343
  }
344
344
  }
345
345
 
@@ -354,10 +354,10 @@ function showMessage(text, type) {
354
354
  function updateTurnIndicator() {
355
355
  const turnIndicator = document.getElementById('turnIndicator');
356
356
  if (gameState.currentPlayer === PLAYER1) {
357
- turnIndicator.textContent = 'תור שחקן 1';
357
+ turnIndicator.textContent = 'Player 1\'s Turn';
358
358
  turnIndicator.className = 'player1-turn';
359
359
  } else {
360
- const text = gameState.gameMode === 'pvc' ? 'תור המחשב' : 'תור שחקן 2';
360
+ const text = gameState.gameMode === 'pvc' ? 'Computer\'s Turn' : 'Player 2\'s Turn';
361
361
  turnIndicator.textContent = text;
362
362
  turnIndicator.className = 'player2-turn';
363
363
  }
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Dice Game</title>
6
+ <title>{{name}} - Dice Game</title>
7
7
  <link rel="stylesheet" href="style.css">
8
8
  </head>
9
9
  <body>
@@ -1,8 +1,8 @@
1
1
  // Game state
2
2
  let gameState = {
3
3
  players: [
4
- { total: 0, current: 0, name: 'שחקן 1' },
5
- { total: 0, current: 0, name: 'שחקן 2' }
4
+ { total: 0, current: 0, name: 'Player 1' },
5
+ { total: 0, current: 0, name: 'Player 2' }
6
6
  ],
7
7
  currentPlayer: 0,
8
8
  gameActive: true,
@@ -34,13 +34,13 @@ function updateDisplay() {
34
34
  if (gameState.currentPlayer === 0) {
35
35
  player1Card.classList.add('active');
36
36
  player2Card.classList.remove('active');
37
- player1Card.querySelector('.current-turn').textContent = 'תורך!';
38
- player2Card.querySelector('.current-turn').textContent = 'המתן...';
37
+ player1Card.querySelector('.current-turn').textContent = 'Your Turn!';
38
+ player2Card.querySelector('.current-turn').textContent = 'Wait...';
39
39
  } else {
40
40
  player1Card.classList.remove('active');
41
41
  player2Card.classList.add('active');
42
- player1Card.querySelector('.current-turn').textContent = 'המתן...';
43
- player2Card.querySelector('.current-turn').textContent = gameState.gameMode === 'pvc' ? 'תור המחשב...' : 'תורך!';
42
+ player1Card.querySelector('.current-turn').textContent = 'Wait...';
43
+ player2Card.querySelector('.current-turn').textContent = gameState.gameMode === 'pvc' ? 'Computer\'s Turn...' : 'Your Turn!';
44
44
  }
45
45
  }
46
46
 
@@ -96,7 +96,7 @@ document.getElementById('rollBtn').addEventListener('click', async () => {
96
96
  if (roll === 1) {
97
97
  // Lost turn
98
98
  gameState.players[gameState.currentPlayer].current = 0;
99
- showMessage(`💥 הטלת 1! איבדת את כל ניקוד התור!`, 'error');
99
+ showMessage(`💥 Rolled 1! You lost all turn points!`, 'error');
100
100
 
101
101
  await new Promise(resolve => setTimeout(resolve, 1500));
102
102
  switchPlayer();
@@ -104,7 +104,7 @@ document.getElementById('rollBtn').addEventListener('click', async () => {
104
104
  // Add to current
105
105
  gameState.players[gameState.currentPlayer].current += roll;
106
106
  updateDisplay();
107
- showMessage(`🎲 הטלת ${roll}!`, 'info');
107
+ showMessage(`🎲 Rolled ${roll}!`, 'info');
108
108
  }
109
109
  });
110
110
 
@@ -115,7 +115,7 @@ document.getElementById('holdBtn').addEventListener('click', () => {
115
115
  const player = gameState.players[gameState.currentPlayer];
116
116
 
117
117
  if (player.current === 0) {
118
- showMessage('אין מה לשמור! הטל קובייה תחילה.', 'error');
118
+ showMessage('Nothing to save! Roll the dice first.', 'error');
119
119
  return;
120
120
  }
121
121
 
@@ -128,7 +128,7 @@ document.getElementById('holdBtn').addEventListener('click', () => {
128
128
  if (player.total >= 100) {
129
129
  endGame();
130
130
  } else {
131
- showMessage(`✅ נשמר! ${player.total} נקודות סה"כ.`, 'success');
131
+ showMessage(`✅ Saved! ${player.total} points total.`, 'success');
132
132
  setTimeout(() => {
133
133
  switchPlayer();
134
134
  }, 1000);
@@ -161,7 +161,7 @@ async function computerTurn() {
161
161
 
162
162
  if (roll === 1) {
163
163
  player.current = 0;
164
- showMessage(`🤖 המחשב הטיל 1! איבד את התור!`, 'error');
164
+ showMessage(`🤖 Computer rolled 1! Lost the turn!`, 'error');
165
165
  await new Promise(resolve => setTimeout(resolve, 1500));
166
166
  switchPlayer();
167
167
  return;
@@ -169,7 +169,7 @@ async function computerTurn() {
169
169
 
170
170
  player.current += roll;
171
171
  updateDisplay();
172
- showMessage(`🤖 המחשב הטיל ${roll}!`, 'info');
172
+ showMessage(`🤖 Computer rolled ${roll}!`, 'info');
173
173
 
174
174
  // AI decision logic
175
175
  const shouldHold =
@@ -189,7 +189,7 @@ async function computerTurn() {
189
189
  return;
190
190
  }
191
191
 
192
- showMessage(`🤖 המחשב שומר ${player.total} נקודות!`, 'success');
192
+ showMessage(`🤖 Computer saves ${player.total} points!`, 'success');
193
193
  await new Promise(resolve => setTimeout(resolve, 1500));
194
194
  switchPlayer();
195
195
  return;
@@ -203,10 +203,10 @@ function endGame() {
203
203
 
204
204
  const winner = gameState.players[gameState.currentPlayer];
205
205
  const winnerName = gameState.currentPlayer === 0 ?
206
- 'שחקן 1' :
207
- (gameState.gameMode === 'pvc' ? 'המחשב' : 'שחקן 2');
206
+ 'Player 1' :
207
+ (gameState.gameMode === 'pvc' ? 'Computer' : 'Player 2');
208
208
 
209
- showMessage(`🎉 ${winnerName} ניצח עם ${winner.total} נקודות!`, 'success');
209
+ showMessage(`🎉 ${winnerName} won with ${winner.total} points!`, 'success');
210
210
 
211
211
  // Celebrate
212
212
  celebrate();
@@ -217,8 +217,8 @@ document.getElementById('newGameBtn').addEventListener('click', newGame);
217
217
 
218
218
  function newGame() {
219
219
  gameState.players = [
220
- { total: 0, current: 0, name: 'שחקן 1' },
221
- { total: 0, current: 0, name: 'שחקן 2' }
220
+ { total: 0, current: 0, name: 'Player 1' },
221
+ { total: 0, current: 0, name: 'Player 2' }
222
222
  ];
223
223
  gameState.currentPlayer = 0;
224
224
  gameState.gameActive = true;
@@ -241,9 +241,9 @@ document.querySelectorAll('.mode-btn').forEach(btn => {
241
241
 
242
242
  // Update player 2 name
243
243
  if (gameState.gameMode === 'pvc') {
244
- document.querySelector('#player2Card h3').textContent = '🤖 מחשב';
244
+ document.querySelector('#player2Card h3').textContent = '🤖 Computer';
245
245
  } else {
246
- document.querySelector('#player2Card h3').textContent = '👤 שחקן 2';
246
+ document.querySelector('#player2Card h3').textContent = '👤 Player 2';
247
247
  }
248
248
 
249
249
  newGame();
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Flappy Bird</title>
6
+ <title>{{name}} - Flappy Bird Game</title>
7
7
  <link rel="stylesheet" href="style.css">
8
8
  </head>
9
9
  <body>