Skip to content

Commit 514cf3f

Browse files
refactor: full technical audit improvements
- CSP meta header + SRI en Font Awesome CDN - Manifest: id, start_url relativa, orientación any, icono SVG - SW: skipWaiting solo por postMessage (showUpdateBanner) - CONFIG con constantes (MAX_WINNERS, MAX_NUMBER_RANGE, etc.) - loadFromLocalStorage con try/catch y limpieza en datos corruptos - AudioContext reutilizado (lazy init), sin fugas de recursos - getSecureRandom() con crypto.getRandomValues y rechazo de sesgo - getParticipantCount() O(1) sin materializar arrays grandes - Debounce en listeners de inputs (150ms) - showConfirm() accesible basado en Promise (reemplaza confirm()) - clearHistory/clearResults/resetStats/clearPreviousWinners async - importFromCSV async con showConfirm agregar/reemplazar - Focus trap y restauración de foco en modal de ganador - showNotification usa clases CSS en lugar de estilos inline - Eliminado fallback execCommand copy (solo Clipboard API) - Keyframes movidos a CSS, eliminada inyección dinámica de estilos - aria-live raffleStatus actualizado durante el sorteo - CI/CD GitHub Actions: validación sintaxis + deploy a GitHub Pages
1 parent 1cd407e commit 514cf3f

6 files changed

Lines changed: 353 additions & 111 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: CI / Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
pages: write
12+
id-token: write
13+
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: false
17+
18+
jobs:
19+
# ── Syntax & basic checks ──────────────────────────────────────────────
20+
check:
21+
name: Lint & Syntax
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- name: Check JS syntax
27+
run: node --check js/app.js sw.js
28+
29+
- name: Validate HTML (vnu)
30+
uses: Cyb3r-Jak3/html5validator-action@v7.2.0
31+
with:
32+
root: .
33+
extra: --skip-non-html
34+
35+
# ── Deploy (main branch only) ──────────────────────────────────────────
36+
deploy:
37+
name: Deploy
38+
needs: check
39+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
40+
runs-on: ubuntu-latest
41+
environment:
42+
name: github-pages
43+
url: ${{ steps.deployment.outputs.page_url }}
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- uses: actions/configure-pages@v4
48+
49+
- uses: actions/upload-pages-artifact@v3
50+
with:
51+
path: '.'
52+
53+
- name: Deploy to GitHub Pages
54+
id: deployment
55+
uses: actions/deploy-pages@v4

css/styles.css

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,67 @@ fieldset.mode-selector {
10221022
}
10231023
}
10241024

1025+
/* ===== NOTIFICATION TOASTS ===== */
1026+
.notification {
1027+
position: fixed;
1028+
top: 100px;
1029+
right: 20px;
1030+
padding: 15px 25px;
1031+
color: white;
1032+
border-radius: 8px;
1033+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
1034+
z-index: 3000;
1035+
animation: slideInRight 0.3s ease;
1036+
font-weight: 600;
1037+
display: flex;
1038+
align-items: center;
1039+
gap: 10px;
1040+
max-width: 360px;
1041+
}
1042+
1043+
.notification--success { background: var(--success-color); }
1044+
.notification--error { background: var(--danger-color); }
1045+
.notification--info { background: #3b82f6; }
1046+
.notification--warning { background: var(--warning-color); }
1047+
1048+
/* ===== CONFIRM DIALOG ===== */
1049+
.modal-content--confirm {
1050+
max-width: 420px;
1051+
}
1052+
1053+
.confirm-message {
1054+
font-size: 1rem;
1055+
color: var(--text-primary);
1056+
margin-bottom: 25px;
1057+
line-height: 1.6;
1058+
white-space: pre-line;
1059+
}
1060+
1061+
.confirm-actions {
1062+
display: flex;
1063+
gap: 12px;
1064+
justify-content: flex-end;
1065+
flex-wrap: wrap;
1066+
}
1067+
1068+
@keyframes confettiFall {
1069+
to {
1070+
transform: translateY(500px) rotate(720deg);
1071+
opacity: 0;
1072+
}
1073+
}
1074+
1075+
@keyframes fadeOut {
1076+
from {
1077+
opacity: 1;
1078+
transform: translateX(0);
1079+
}
1080+
to {
1081+
opacity: 0;
1082+
transform: translateX(20px);
1083+
}
1084+
}
1085+
10251086
/* Scrollbar Styling */
10261087
::-webkit-scrollbar {
10271088
width: 10px;

index.html

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<html lang="es">
33
<head>
44
<meta charset="UTF-8">
5+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src https://cdnjs.cloudflare.com; script-src 'self'; worker-src 'self'; img-src 'self' data: blob:; connect-src 'self' https://cdnjs.cloudflare.com; frame-ancestors 'none'">
56
<meta name="viewport" content="width=device-width, initial-scale=1.0">
67
<meta name="description" content="Generador de rifas profesional para sorteos con nombres o números. Ideal para rifas, concursos y eventos.">
78
<meta name="theme-color" content="#6366f1">
@@ -13,7 +14,7 @@
1314
<link rel="apple-touch-icon" href="icons/icon.svg">
1415
<title>Generador de Rifas Profesional</title>
1516
<link rel="stylesheet" href="css/styles.css">
16-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
17+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer">
1718
</head>
1819
<body>
1920
<!-- Controles de tema -->
@@ -35,7 +36,7 @@
3536
</div>
3637
</div>
3738

38-
<div class="container">
39+
<main class="container">
3940
<header class="header" role="banner">
4041
<h1><i class="fas fa-ticket-alt" aria-hidden="true"></i> Generador de Rifas Profesional</h1>
4142
<p class="subtitle">Sistema avanzado para sorteos con nombres o números</p>
@@ -238,6 +239,17 @@ <h3><i class="fas fa-history"></i> Historial</h3>
238239
</button>
239240
</div>
240241
</div>
242+
</main>
243+
244+
<!-- Modal de confirmación -->
245+
<div class="modal" id="confirmModal" role="dialog" aria-modal="true" aria-labelledby="confirmMessage">
246+
<div class="modal-content modal-content--confirm">
247+
<p id="confirmMessage" class="confirm-message"></p>
248+
<div class="confirm-actions">
249+
<button class="btn btn-primary" id="confirmOk" type="button">Aceptar</button>
250+
<button class="btn btn-secondary" id="confirmCancel" type="button">Cancelar</button>
251+
</div>
252+
</div>
241253
</div>
242254

243255
<!-- Modal de ganador -->
@@ -251,7 +263,7 @@ <h2 id="modalTitle">¡Felicidades!</h2>
251263
</div>
252264
</div>
253265

254-
<footer class="footer">
266+
<footer class="footer" role="contentinfo">
255267
<p>Generador de Rifas Profesional v1.0 | Desarrollado con <i class="fas fa-heart"></i></p>
256268
</footer>
257269

0 commit comments

Comments
 (0)