- manifest.webmanifest + service worker (offline shell, /api network-only, asset stale-while-revalidate) - set icone (192/512 + maskable + apple-touch + favicon), generate zero-deps (pure Node+zlib) - tag PWA + viewport viewport-fit=cover (zoom mantenuto, WCAG 1.4.4) in 77 pagine HTML - AGID/WCAG 2.1 AA: touch target >=44px, orientamento/zoom liberi, safe-area standalone - generatori riproducibili: scripts/gen-pwa-icons.mjs + scripts/inject-pwa-head.mjs - bump version 1.14.1 -> 1.15.0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
90 lines
4.3 KiB
HTML
90 lines
4.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="it">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
<title>Bootstrap Italia self-host — smoke test</title>
|
|
<!-- SELF-HOSTED Bootstrap Italia v2.18.1 — asset LOCALI da /vendor, ZERO CDN -->
|
|
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
|
|
<!-- PWA:start -->
|
|
<link rel="manifest" href="/manifest.webmanifest">
|
|
<meta name="theme-color" content="#0066CC">
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/assets/icons/favicon-32.png">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/icons/favicon-16.png">
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/assets/icons/apple-touch-icon.png">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
|
<meta name="apple-mobile-web-app-title" content="NIS2 Agile">
|
|
<meta name="application-name" content="NIS2 Agile">
|
|
<script src="/js/pwa.js?v=20260614" defer></script>
|
|
<!-- PWA:end -->
|
|
</head>
|
|
<body>
|
|
<main class="container py-4" id="main-content">
|
|
<h1 class="h3 mb-2">Bootstrap Italia — smoke test (self-host)</h1>
|
|
<p class="text-muted">
|
|
CSS, JS e font serviti localmente da <code>/vendor/bootstrap-italia/</code>.
|
|
Nessun riferimento a CDN.
|
|
</p>
|
|
|
|
<div class="alert alert-info" role="status" id="bi-status">
|
|
Verifica caricamento JS in corso...
|
|
</div>
|
|
|
|
<section aria-labelledby="form-title" class="mt-4">
|
|
<h2 class="h5" id="form-title">Form di prova</h2>
|
|
<form id="smoke-form" novalidate>
|
|
<div class="form-group">
|
|
<label for="smoke-input" class="active">Campo di prova</label>
|
|
<input type="text" id="smoke-input" name="smoke-input"
|
|
class="form-control" autocomplete="off"
|
|
aria-describedby="smoke-help">
|
|
<small id="smoke-help" class="form-text text-muted">
|
|
Esempio di <code>.form-control</code> Bootstrap Italia.
|
|
</small>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary" id="smoke-btn">
|
|
Bottone primario
|
|
</button>
|
|
<button type="button" class="btn btn-outline-primary ms-2" id="smoke-icon-btn"
|
|
aria-label="Pulsante con icona di prova">
|
|
<svg class="icon icon-sm" aria-hidden="true">
|
|
<use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-check-circle"></use>
|
|
</svg>
|
|
<span>Icona locale</span>
|
|
</button>
|
|
</form>
|
|
</section>
|
|
</main>
|
|
|
|
<!-- JS bundle LOCALE -->
|
|
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
|
|
<script>
|
|
// Carica i web font ufficiali (Titillium Web, Lora, Roboto Mono) — TUTTI LOCALI
|
|
(function () {
|
|
var statusEl = document.getElementById('bi-status');
|
|
if (window.bootstrap && typeof bootstrap.loadFonts === 'function') {
|
|
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
|
|
statusEl.className = 'alert alert-success';
|
|
statusEl.setAttribute('role', 'status');
|
|
statusEl.textContent = 'OK: Bootstrap Italia JS caricato dal vendor locale e bootstrap.loadFonts() invocato su /vendor/bootstrap-italia/dist/fonts.';
|
|
} else {
|
|
statusEl.className = 'alert alert-danger';
|
|
statusEl.setAttribute('role', 'alert');
|
|
statusEl.textContent = 'ERRORE: bootstrap.loadFonts non disponibile (JS non caricato).';
|
|
}
|
|
})();
|
|
|
|
document.getElementById('smoke-form').addEventListener('submit', function (e) {
|
|
e.preventDefault();
|
|
var s = document.getElementById('bi-status');
|
|
s.className = 'alert alert-success';
|
|
s.textContent = 'Form inviato (smoke): JS interattivo funzionante. Valore = "' +
|
|
document.getElementById('smoke-input').value + '"';
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|