akhaliq HF Staff commited on
Commit
ac1552a
·
verified ·
1 Parent(s): 2ade2dd

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +670 -19
index.html CHANGED
@@ -1,19 +1,670 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Modern Todo App</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
8
+ <style>
9
+ :root {
10
+ --primary-color: #6366f1;
11
+ --primary-dark: #4f46e5;
12
+ --secondary-color: #8b5cf6;
13
+ --success-color: #10b981;
14
+ --danger-color: #ef4444;
15
+ --warning-color: #f59e0b;
16
+ --dark-color: #1f2937;
17
+ --light-color: #f3f4f6;
18
+ --white: #ffffff;
19
+ --gray-100: #f9fafb;
20
+ --gray-200: #f3f4f6;
21
+ --gray-300: #e5e7eb;
22
+ --gray-400: #d1d5db;
23
+ --gray-500: #9ca3af;
24
+ --gray-600: #6b7280;
25
+ --gray-700: #4b5563;
26
+ --gray-800: #374151;
27
+ --gray-900: #1f2937;
28
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
29
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
30
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
31
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
32
+ }
33
+
34
+ * {
35
+ margin: 0;
36
+ padding: 0;
37
+ box-sizing: border-box;
38
+ }
39
+
40
+ body {
41
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
42
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
43
+ min-height: 100vh;
44
+ display: flex;
45
+ justify-content: center;
46
+ align-items: center;
47
+ padding: 20px;
48
+ color: var(--dark-color);
49
+ }
50
+
51
+ .container {
52
+ width: 100%;
53
+ max-width: 600px;
54
+ background: var(--white);
55
+ border-radius: 20px;
56
+ box-shadow: var(--shadow-xl);
57
+ overflow: hidden;
58
+ animation: slideUp 0.5s ease-out;
59
+ }
60
+
61
+ @keyframes slideUp {
62
+ from {
63
+ opacity: 0;
64
+ transform: translateY(30px);
65
+ }
66
+ to {
67
+ opacity: 1;
68
+ transform: translateY(0);
69
+ }
70
+ }
71
+
72
+ .header {
73
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
74
+ padding: 25px 30px;
75
+ text-align: center;
76
+ position: relative;
77
+ }
78
+
79
+ .header h1 {
80
+ color: var(--white);
81
+ font-size: 28px;
82
+ font-weight: 700;
83
+ margin-bottom: 10px;
84
+ }
85
+
86
+ .anycoder-link {
87
+ color: var(--white);
88
+ text-decoration: none;
89
+ font-size: 14px;
90
+ opacity: 0.9;
91
+ transition: opacity 0.3s ease;
92
+ display: inline-flex;
93
+ align-items: center;
94
+ gap: 5px;
95
+ }
96
+
97
+ .anycoder-link:hover {
98
+ opacity: 1;
99
+ }
100
+
101
+ .main-content {
102
+ padding: 30px;
103
+ }
104
+
105
+ .add-todo {
106
+ display: flex;
107
+ gap: 12px;
108
+ margin-bottom: 25px;
109
+ }
110
+
111
+ .add-todo input {
112
+ flex: 1;
113
+ padding: 14px 20px;
114
+ border: 2px solid var(--gray-200);
115
+ border-radius: 12px;
116
+ font-size: 16px;
117
+ transition: all 0.3s ease;
118
+ }
119
+
120
+ .add-todo input:focus {
121
+ outline: none;
122
+ border-color: var(--primary-color);
123
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
124
+ }
125
+
126
+ .add-todo button {
127
+ padding: 14px 24px;
128
+ background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
129
+ color: var(--white);
130
+ border: none;
131
+ border-radius: 12px;
132
+ font-size: 16px;
133
+ font-weight: 600;
134
+ cursor: pointer;
135
+ transition: all 0.3s ease;
136
+ display: flex;
137
+ align-items: center;
138
+ gap: 8px;
139
+ }
140
+
141
+ .add-todo button:hover {
142
+ transform: translateY(-2px);
143
+ box-shadow: var(--shadow-lg);
144
+ }
145
+
146
+ .filters {
147
+ display: flex;
148
+ gap: 10px;
149
+ margin-bottom: 25px;
150
+ background: var(--gray-100);
151
+ padding: 5px;
152
+ border-radius: 12px;
153
+ }
154
+
155
+ .filter-btn {
156
+ flex: 1;
157
+ padding: 10px;
158
+ border: none;
159
+ background: transparent;
160
+ border-radius: 8px;
161
+ cursor: pointer;
162
+ font-size: 14px;
163
+ font-weight: 500;
164
+ color: var(--gray-600);
165
+ transition: all 0.3s ease;
166
+ }
167
+
168
+ .filter-btn.active {
169
+ background: var(--white);
170
+ color: var(--primary-color);
171
+ box-shadow: var(--shadow-sm);
172
+ }
173
+
174
+ .todo-list {
175
+ list-style: none;
176
+ margin-bottom: 25px;
177
+ min-height: 300px;
178
+ }
179
+
180
+ .todo-item {
181
+ display: flex;
182
+ align-items: center;
183
+ padding: 16px;
184
+ background: var(--white);
185
+ border: 2px solid var(--gray-200);
186
+ border-radius: 12px;
187
+ margin-bottom: 12px;
188
+ transition: all 0.3s ease;
189
+ animation: fadeIn 0.3s ease-out;
190
+ }
191
+
192
+ @keyframes fadeIn {
193
+ from {
194
+ opacity: 0;
195
+ transform: translateX(-20px);
196
+ }
197
+ to {
198
+ opacity: 1;
199
+ transform: translateX(0);
200
+ }
201
+ }
202
+
203
+ .todo-item:hover {
204
+ border-color: var(--primary-color);
205
+ box-shadow: var(--shadow-md);
206
+ }
207
+
208
+ .todo-item.completed {
209
+ opacity: 0.7;
210
+ background: var(--gray-50);
211
+ }
212
+
213
+ .todo-item.completed .todo-text {
214
+ text-decoration: line-through;
215
+ color: var(--gray-500);
216
+ }
217
+
218
+ .todo-checkbox {
219
+ width: 22px;
220
+ height: 22px;
221
+ border: 2px solid var(--gray-400);
222
+ border-radius: 6px;
223
+ margin-right: 15px;
224
+ cursor: pointer;
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ transition: all 0.3s ease;
229
+ }
230
+
231
+ .todo-checkbox.checked {
232
+ background: var(--success-color);
233
+ border-color: var(--success-color);
234
+ }
235
+
236
+ .todo-checkbox.checked::after {
237
+ content: '✓';
238
+ color: var(--white);
239
+ font-size: 14px;
240
+ font-weight: bold;
241
+ }
242
+
243
+ .todo-text {
244
+ flex: 1;
245
+ font-size: 16px;
246
+ color: var(--dark-color);
247
+ }
248
+
249
+ .todo-actions {
250
+ display: flex;
251
+ gap: 8px;
252
+ }
253
+
254
+ .todo-actions button {
255
+ width: 32px;
256
+ height: 32px;
257
+ border: none;
258
+ border-radius: 8px;
259
+ background: var(--gray-100);
260
+ color: var(--gray-600);
261
+ cursor: pointer;
262
+ display: flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ transition: all 0.3s ease;
266
+ }
267
+
268
+ .todo-actions button:hover {
269
+ background: var(--gray-200);
270
+ }
271
+
272
+ .todo-actions button.delete:hover {
273
+ background: var(--danger-color);
274
+ color: var(--white);
275
+ }
276
+
277
+ .todo-actions button.edit:hover {
278
+ background: var(--primary-color);
279
+ color: var(--white);
280
+ }
281
+
282
+ .stats {
283
+ display: flex;
284
+ justify-content: space-between;
285
+ padding: 15px 20px;
286
+ background: var(--gray-100);
287
+ border-radius: 12px;
288
+ font-size: 14px;
289
+ color: var(--gray-600);
290
+ }
291
+
292
+ .stat-item {
293
+ display: flex;
294
+ align-items: center;
295
+ gap: 5px;
296
+ }
297
+
298
+ .empty-state {
299
+ text-align: center;
300
+ padding: 40px 20px;
301
+ color: var(--gray-500);
302
+ }
303
+
304
+ .empty-state i {
305
+ font-size: 48px;
306
+ margin-bottom: 15px;
307
+ opacity: 0.5;
308
+ }
309
+
310
+ .empty-state p {
311
+ font-size: 16px;
312
+ margin-bottom: 20px;
313
+ }
314
+
315
+ .clear-completed {
316
+ background: transparent;
317
+ border: none;
318
+ color: var(--danger-color);
319
+ cursor: pointer;
320
+ font-size: 14px;
321
+ padding: 5px 10px;
322
+ border-radius: 6px;
323
+ transition: all 0.3s ease;
324
+ }
325
+
326
+ .clear-completed:hover {
327
+ background: var(--danger-color);
328
+ color: var(--white);
329
+ }
330
+
331
+ .edit-modal {
332
+ display: none;
333
+ position: fixed;
334
+ top: 0;
335
+ left: 0;
336
+ width: 100%;
337
+ height: 100%;
338
+ background: rgba(0, 0, 0, 0.5);
339
+ align-items: center;
340
+ justify-content: center;
341
+ z-index: 1000;
342
+ }
343
+
344
+ .edit-modal.active {
345
+ display: flex;
346
+ }
347
+
348
+ .edit-modal-content {
349
+ background: var(--white);
350
+ padding: 25px;
351
+ border-radius: 16px;
352
+ width: 90%;
353
+ max-width: 400px;
354
+ animation: modalSlideIn 0.3s ease-out;
355
+ }
356
+
357
+ @keyframes modalSlideIn {
358
+ from {
359
+ opacity: 0;
360
+ transform: scale(0.9);
361
+ }
362
+ to {
363
+ opacity: 1;
364
+ transform: scale(1);
365
+ }
366
+ }
367
+
368
+ .edit-modal h3 {
369
+ margin-bottom: 15px;
370
+ color: var(--dark-color);
371
+ }
372
+
373
+ .edit-modal input {
374
+ width: 100%;
375
+ padding: 12px;
376
+ border: 2px solid var(--gray-200);
377
+ border-radius: 10px;
378
+ font-size: 16px;
379
+ margin-bottom: 15px;
380
+ }
381
+
382
+ .edit-modal-buttons {
383
+ display: flex;
384
+ gap: 10px;
385
+ }
386
+
387
+ .edit-modal-buttons button {
388
+ flex: 1;
389
+ padding: 12px;
390
+ border: none;
391
+ border-radius: 10px;
392
+ font-size: 14px;
393
+ font-weight: 600;
394
+ cursor: pointer;
395
+ transition: all 0.3s ease;
396
+ }
397
+
398
+ .edit-modal-buttons button.save {
399
+ background: var(--success-color);
400
+ color: var(--white);
401
+ }
402
+
403
+ .edit-modal-buttons button.cancel {
404
+ background: var(--gray-200);
405
+ color: var(--dark-color);
406
+ }
407
+
408
+ .edit-modal-buttons button:hover {
409
+ transform: translateY(-2px);
410
+ box-shadow: var(--shadow-md);
411
+ }
412
+
413
+ @media (max-width: 480px) {
414
+ .container {
415
+ border-radius: 15px;
416
+ }
417
+
418
+ .header h1 {
419
+ font-size: 24px;
420
+ }
421
+
422
+ .main-content {
423
+ padding: 20px;
424
+ }
425
+
426
+ .add-todo {
427
+ flex-direction: column;
428
+ }
429
+
430
+ .filters {
431
+ flex-wrap: wrap;
432
+ }
433
+
434
+ .todo-item {
435
+ padding: 12px;
436
+ }
437
+
438
+ .todo-text {
439
+ font-size: 14px;
440
+ }
441
+ }
442
+ </style>
443
+ </head>
444
+ <body>
445
+ <div class="container">
446
+ <div class="header">
447
+ <h1>📝 Modern Todo App</h1>
448
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="anycoder-link" target="_blank">
449
+ <i class="fas fa-code"></i> Built with anycoder
450
+ </a>
451
+ </div>
452
+
453
+ <div class="main-content">
454
+ <div class="add-todo">
455
+ <input type="text" id="todoInput" placeholder="What needs to be done?" />
456
+ <button id="addBtn">
457
+ <i class="fas fa-plus"></i> Add Todo
458
+ </button>
459
+ </div>
460
+
461
+ <div class="filters">
462
+ <button class="filter-btn active" data-filter="all">All</button>
463
+ <button class="filter-btn" data-filter="active">Active</button>
464
+ <button class="filter-btn" data-filter="completed">Completed</button>
465
+ </div>
466
+
467
+ <ul class="todo-list" id="todoList"></ul>
468
+
469
+ <div class="stats">
470
+ <div class="stat-item">
471
+ <i class="fas fa-list"></i>
472
+ <span id="totalTodos">0 total</span>
473
+ </div>
474
+ <div class="stat-item">
475
+ <i class="fas fa-check-circle"></i>
476
+ <span id="completedTodos">0 completed</span>
477
+ </div>
478
+ <div class="stat-item">
479
+ <i class="fas fa-circle"></i>
480
+ <span id="activeTodos">0 active</span>
481
+ </div>
482
+ <button class="clear-completed" id="clearCompleted">
483
+ <i class="fas fa-trash"></i> Clear Completed
484
+ </button>
485
+ </div>
486
+ </div>
487
+ </div>
488
+
489
+ <div class="edit-modal" id="editModal">
490
+ <div class="edit-modal-content">
491
+ <h3>Edit Todo</h3>
492
+ <input type="text" id="editInput" />
493
+ <div class="edit-modal-buttons">
494
+ <button class="save" id="saveEdit">Save</button>
495
+ <button class="cancel" id="cancelEdit">Cancel</button>
496
+ </div>
497
+ </div>
498
+ </div>
499
+
500
+ <script>
501
+ class TodoApp {
502
+ constructor() {
503
+ this.todos = JSON.parse(localStorage.getItem('todos')) || [];
504
+ this.currentFilter = 'all';
505
+ this.editingIndex = -1;
506
+ this.init();
507
+ }
508
+
509
+ init() {
510
+ this.bindEvents();
511
+ this.render();
512
+ this.updateStats();
513
+ }
514
+
515
+ bindEvents() {
516
+ document.getElementById('addBtn').addEventListener('click', () => this.addTodo());
517
+ document.getElementById('todoInput').addEventListener('keypress', (e) => {
518
+ if (e.key === 'Enter') this.addTodo();
519
+ });
520
+
521
+ document.querySelectorAll('.filter-btn').forEach(btn => {
522
+ btn.addEventListener('click', (e) => {
523
+ document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
524
+ e.target.classList.add('active');
525
+ this.currentFilter = e.target.dataset.filter;
526
+ this.render();
527
+ });
528
+ });
529
+
530
+ document.getElementById('clearCompleted').addEventListener('click', () => this.clearCompleted());
531
+ document.getElementById('saveEdit').addEventListener('click', () => this.saveEdit());
532
+ document.getElementById('cancelEdit').addEventListener('click', () => this.closeEditModal());
533
+ }
534
+
535
+ addTodo() {
536
+ const input = document.getElementById('todoInput');
537
+ const text = input.value.trim();
538
+
539
+ if (text) {
540
+ this.todos.push({
541
+ text,
542
+ completed: false,
543
+ createdAt: new Date().toISOString()
544
+ });
545
+ input.value = '';
546
+ this.saveToLocalStorage();
547
+ this.render();
548
+ this.updateStats();
549
+ }
550
+ }
551
+
552
+ toggleTodo(index) {
553
+ this.todos[index].completed = !this.todos[index].completed;
554
+ this.saveToLocalStorage();
555
+ this.render();
556
+ this.updateStats();
557
+ }
558
+
559
+ deleteTodo(index) {
560
+ this.todos.splice(index, 1);
561
+ this.saveToLocalStorage();
562
+ this.render();
563
+ this.updateStats();
564
+ }
565
+
566
+ editTodo(index) {
567
+ this.editingIndex = index;
568
+ const todo = this.todos[index];
569
+ document.getElementById('editInput').value = todo.text;
570
+ document.getElementById('editModal').classList.add('active');
571
+ }
572
+
573
+ saveEdit() {
574
+ const newText = document.getElementById('editInput').value.trim();
575
+ if (newText && this.editingIndex !== -1) {
576
+ this.todos[this.editingIndex].text = newText;
577
+ this.saveToLocalStorage();
578
+ this.render();
579
+ this.closeEditModal();
580
+ }
581
+ }
582
+
583
+ closeEditModal() {
584
+ document.getElementById('editModal').classList.remove('active');
585
+ this.editingIndex = -1;
586
+ }
587
+
588
+ clearCompleted() {
589
+ this.todos = this.todos.filter(todo => !todo.completed);
590
+ this.saveToLocalStorage();
591
+ this.render();
592
+ this.updateStats();
593
+ }
594
+
595
+ getFilteredTodos() {
596
+ switch (this.currentFilter) {
597
+ case 'active':
598
+ return this.todos.filter(todo => !todo.completed);
599
+ case 'completed':
600
+ return this.todos.filter(todo => todo.completed);
601
+ default:
602
+ return this.todos;
603
+ }
604
+ }
605
+
606
+ render() {
607
+ const todoList = document.getElementById('todoList');
608
+ const filteredTodos = this.getFilteredTodos();
609
+
610
+ if (filteredTodos.length === 0) {
611
+ todoList.innerHTML = `
612
+ <div class="empty-state">
613
+ <i class="fas fa-clipboard-list"></i>
614
+ <p>No todos found</p>
615
+ <p>Add a new todo to get started!</p>
616
+ </div>
617
+ `;
618
+ return;
619
+ }
620
+
621
+ todoList.innerHTML = filteredTodos.map((todo, index) => {
622
+ const actualIndex = this.todos.findIndex(t => t === todo);
623
+ return `
624
+ <li class="todo-item ${todo.completed ? 'completed' : ''}">
625
+ <div class="todo-checkbox ${todo.completed ? 'checked' : ''}"
626
+ onclick="todoApp.toggleTodo(${actualIndex})"></div>
627
+ <span class="todo-text">${this.escapeHtml(todo.text)}</span>
628
+ <div class="todo-actions">
629
+ <button class="edit" onclick="todoApp.editTodo(${actualIndex})">
630
+ <i class="fas fa-edit"></i>
631
+ </button>
632
+ <button class="delete" onclick="todoApp.deleteTodo(${actualIndex})">
633
+ <i class="fas fa-trash"></i>
634
+ </button>
635
+ </div>
636
+ </li>
637
+ `;
638
+ }).join('');
639
+ }
640
+
641
+ updateStats() {
642
+ const total = this.todos.length;
643
+ const completed = this.todos.filter(todo => todo.completed).length;
644
+ const active = total - completed;
645
+
646
+ document.getElementById('totalTodos').textContent = `${total} total`;
647
+ document.getElementById('completedTodos').textContent = `${completed} completed`;
648
+ document.getElementById('activeTodos').textContent = `${active} active`;
649
+ }
650
+
651
+ saveToLocalStorage() {
652
+ localStorage.setItem('todos', JSON.stringify(this.todos));
653
+ }
654
+
655
+ escapeHtml(text) {
656
+ const map = {
657
+ '&': '&amp;',
658
+ '<': '&lt;',
659
+ '>': '&gt;',
660
+ '"': '&quot;',
661
+ "'": '&#039;'
662
+ };
663
+ return text.replace(/[&<>"']/g, m => map[m]);
664
+ }
665
+ }
666
+
667
+ const todoApp = new TodoApp();
668
+ </script>
669
+ </body>
670
+ </html>