<header>, <nav>, <article>, <section>, <footer><audio> e <video><!DOCTYPE html>
<html lang="pt-PT">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Descrição da página">
<title>Título da Página</title>
<link rel="stylesheet" href="estilos.css">
</head>
<body>
<!-- Conteúdo da página -->
<h1>Olá, mundo!</h1>
<p>Esta é a minha primeira página HTML5.</p>
</body>
</html><!DOCTYPE html>: declaração do tipo de documento<html lang="pt-PT">: elemento raiz com idioma definido<head>: metadados e informações sobre o documento<meta charset="UTF-8">: define a codificação de caracteres<title>: título que aparece no separador do navegador<body>: conteúdo visível da página<h1>Título principal</h1>
<h2>Subtítulo</h2>
<h3>Sub-subtítulo</h3>
<h4>Título nível 4</h4>
<h5>Título nível 5</h5>
<h6>Título nível 6</h6><p>Este é um parágrafo de texto.</p>
<p>Este é outro parágrafo.<br>
Com uma quebra de linha dentro.</p><!-- Lista não ordenada -->
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<!-- Lista ordenada -->
<ol>
<li>Primeiro item</li>
<li>Segundo item</li>
<li>Terceiro item</li>
</ol>
<!-- Lista de definições -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets</dd>
</dl><div class="container">
<p>Conteúdo dentro de uma div</p>
</div>
<span class="destaque">Texto destacado</span><p>Este texto tem <strong>ênfase forte</strong> e <em>ênfase itálica</em>.</p>
<p>Texto <mark>marcado</mark> e <del>removido</del>.</p>
<p>Texto <sub>subscrito</sub> e <sup>sobrescrito</sup>.</p>
<p>Pequeno texto: <small>Copyright 2024</small></p><blockquote cite="https://exemplo.com">
<p>Esta é uma citação em bloco.</p>
</blockquote>
<p>Como disse alguém, <q cite="https://exemplo.com">esta é uma citação inline</q>.</p><p>O comando <code>console.log()</code> é usado em JavaScript.</p>
<pre>
<code>
function saudacao() {
console.log("Olá, mundo!");
}
</code>
</pre><img src="imagem.jpg"
alt="Descrição da imagem"
width="300"
height="200"
loading="lazy"><audio controls>
<source src="musica.mp3" type="audio/mpeg">
<source src="musica.ogg" type="audio/ogg">
O seu navegador não suporta o elemento áudio.
</audio><video width="640" height="360" controls poster="miniatura.jpg">
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<track src="legendas.vtt" kind="subtitles" srclang="pt" label="Português">
O seu navegador não suporta o elemento vídeo.
</video><figure>
<img src="grafico.png" alt="Gráfico de vendas">
<figcaption>Figura 1: Evolução das vendas em 2024</figcaption>
</figure><a href="https://www.exemplo.com" target="_blank" rel="noopener noreferrer">
Visitar exemplo.com
</a><a href="#secao2">Ir para secção 2</a>
<!-- Mais tarde na página -->
<section id="secao2">
<h2>Secção 2</h2>
<p>Conteúdo da secção 2...</p>
</section><a href="mailto:contacto@exemplo.com">Enviar email</a>
<a href="tel:+351123456789">Ligar para +351 123 456 789</a><nav>
<ul>
<li><a href="/">Início</a></li>
<li><a href="/sobre">Sobre</a></li>
<li><a href="/servicos">Serviços</a></li>
<li><a href="/contacto">Contacto</a></li>
</ul>
</nav><table>
<caption>Vendas mensais</caption>
<thead>
<tr>
<th>Mês</th>
<th>Vendas</th>
<th>Lucro</th>
</tr>
</thead>
<tbody>
<tr>
<td>Janeiro</td>
<td>1000€</td>
<td>200€</td>
</tr>
<tr>
<td>Fevereiro</td>
<td>1200€</td>
<td>250€</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Total</td>
<td>2200€</td>
<td>450€</td>
</tr>
</tfoot>
</table><table>
<colgroup>
<col span="2" style="background-color: #f0f0f0;">
<col style="background-color: #e0e0e0;">
</colgroup>
<thead>
<tr>
<th scope="col">Produto</th>
<th scope="col">Quantidade</th>
<th scope="col">Preço</th>
</tr>
</thead>
<tbody>
<tr>
<td>Computador</td>
<td>5</td>
<td>800€</td>
</tr>
</tbody>
</table><form action="/processar" method="POST">
<div>
<label for="nome">Nome:</label>
<input type="text" id="nome" name="nome" required>
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div>
<label for="mensagem">Mensagem:</label>
<textarea id="mensagem" name="mensagem" rows="5" cols="30"></textarea>
</div>
<button type="submit">Enviar</button>
</form><form>
<!-- Texto -->
<input type="text" placeholder="Texto simples">
<!-- Email -->
<input type="email" placeholder="email@exemplo.com">
<!-- Telefone -->
<input type="tel" placeholder="+351 123 456 789">
<!-- URL -->
<input type="url" placeholder="https://exemplo.com">
<!-- Número -->
<input type="number" min="0" max="100" step="5">
<!-- Intervalo -->
<input type="range" min="0" max="100" value="50">
<!-- Data -->
<input type="date">
<!-- Hora -->
<input type="time">
<!-- Data e hora local -->
<input type="datetime-local">
<!-- Mês -->
<input type="month">
<!-- Semana -->
<input type="week">
<!-- Cor -->
<input type="color">
<!-- Procura -->
<input type="search" placeholder="Pesquisar...">
<!-- Password -->
<input type="password" placeholder="Palavra-passe">
<!-- Ficheiro -->
<input type="file" accept="image/*" multiple>
</form><form>
<!-- Lista de opções -->
<input list="browsers" name="browser">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
</datalist>
<!-- Campo com medidor -->
<label for="disco">Uso de disco:</label>
<meter id="disco" value="6" min="0" max="10">6 de 10</meter>
<!-- Progresso -->
<label for="progresso">Progresso:</label>
<progress id="progresso" value="70" max="100">70%</progress>
<!-- Grupo de campos -->
<fieldset>
<legend>Informações pessoais</legend>
<label for="nome">Nome:</label>
<input type="text" id="nome" name="nome">
<label for="idade">Idade:</label>
<input type="number" id="idade" name="idade">
</fieldset>
</form><!DOCTYPE html>
<html lang="pt-PT">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Exemplo Semântico</title>
</head>
<body>
<header>
<h1>Logo ou título do site</h1>
<nav>
<ul>
<li><a href="/">Início</a></li>
<li><a href="/sobre">Sobre</a></li>
<li><a href="/contacto">Contacto</a></li>
</ul>
</nav>
</header>
<main>
<article>
<header>
<h2>Título do artigo</h2>
<p>Publicado em <time datetime="2024-01-15">15 de Janeiro de 2024</time></p>
</header>
<section>
<h3>Introdução</h3>
<p>Conteúdo da introdução...</p>
</section>
<section>
<h3>Desenvolvimento</h3>
<p>Conteúdo do desenvolvimento...</p>
</section>
<aside>
<h4>Informação relacionada</h4>
<p>Conteúdo complementar...</p>
</aside>
</article>
<section>
<h2>Outra secção</h2>
<p>Conteúdo adicional...</p>
</section>
</main>
<footer>
<p>© 2024 Nome do Site. Todos os direitos reservados.</p>
<address>
Contacto: <a href="mailto:info@exemplo.com">info@exemplo.com</a>
</address>
</footer>
</body>
</html><!-- Detalhes expansíveis -->
<details>
<summary>Clique para expandir</summary>
<p>Conteúdo oculto que aparece quando clicado.</p>
</details>
<!-- Marcação de texto importante -->
<p>O <strong>HTML5</strong> é importante para a web moderna.</p>
<!-- Marcação de ênfase -->
<p>Este <em>texto</em> está em itálico por ênfase.</p>
<!-- Pequenas impressões -->
<p><small>© 2024 Todos os direitos reservados</small></p>
<!-- Marcação de tempo -->
<p>O evento ocorreu em <time datetime="2024-01-15">15 de Janeiro</time>.</p><!DOCTYPE html>
<html>
<head>
<title>LocalStorage Exemplo</title>
</head>
<body>
<input type="text" id="dados" placeholder="Escreva algo">
<button onclick="guardar()">Guardar</button>
<button onclick="recuperar()">Recuperar</button>
<p id="resultado"></p>
<script>
function guardar() {
const valor = document.getElementById('dados').value;
localStorage.setItem('meusDados', valor);
alert('Dados guardados!');
}
function recuperar() {
const valor = localStorage.getItem('meusDados');
document.getElementById('resultado').textContent = valor || 'Nenhum dado encontrado';
}
</script>
</body>
</html>// Guardar dados na sessão
sessionStorage.setItem('usuario', 'João');
// Recuperar dados
const usuario = sessionStorage.getItem('usuario');
// Remover dados
sessionStorage.removeItem('usuario');
// Limpar tudo
sessionStorage.clear();<!DOCTYPE html>
<html>
<head>
<title>Geolocalização</title>
</head>
<body>
<button onclick="obterLocalizacao()">Obter minha localização</button>
<p id="demo"></p>
<script>
function obterLocalizacao() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(mostrarPosicao, mostrarErro);
} else {
document.getElementById("demo").innerHTML = "Geolocalização não é suportada.";
}
}
function mostrarPosicao(posicao) {
document.getElementById("demo").innerHTML =
"Latitude: " + posicao.coords.latitude +
"<br>Longitude: " + posicao.coords.longitude;
}
function mostrarErro(erro) {
switch(erro.code) {
case erro.PERMISSION_DENIED:
document.getElementById("demo").innerHTML = "Utilizador negou a solicitação.";
break;
case erro.POSITION_UNAVAILABLE:
document.getElementById("demo").innerHTML = "Informação de localização indisponível.";
break;
case erro.TIMEOUT:
document.getElementById("demo").innerHTML = "A solicitação expirou.";
break;
default:
document.getElementById("demo").innerHTML = "Ocorreu um erro desconhecido.";
break;
}
}
</script>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Drag and Drop</title>
<style>
#div1 {
width: 350px;
height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
}
</style>
</head>
<body>
<p>Arraste a imagem para a caixa:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="img_logo.gif" draggable="true" ondragstart="drag(event)" width="336" height="69">
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Canvas Exemplo</title>
</head>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;">
O seu navegador não suporta o elemento canvas.
</canvas>
<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
// Desenhar um retângulo
ctx.fillStyle = "#FF0000";
ctx.fillRect(10, 10, 150, 80);
// Desenhar uma linha
ctx.moveTo(0, 0);
ctx.lineTo(200, 100);
ctx.stroke();
// Desenhar um círculo
ctx.beginPath();
ctx.arc(95, 50, 40, 0, 2 * Math.PI);
ctx.stroke();
// Texto
ctx.font = "30px Arial";
ctx.fillText("Olá", 10, 50);
</script>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>SVG Exemplo</title>
</head>
<body>
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
<svg width="400" height="110">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
<svg height="210" width="500">
<polygon points="200,10 250,190 160,210" style="fill:lime;stroke:purple;stroke-width:1" />
</svg>
<svg height="60" width="200">
<text x="0" y="15" fill="red" transform="rotate(30 20,40)">Olá SVG!</text>
</svg>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Animação Canvas</title>
</head>
<body>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #000000;"></canvas>
<script>
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
let x = 0;
let y = 75;
let dx = 2;
function desenhar() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(x, y, 20, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
x += dx;
if(x + 20 > canvas.width || x - 20 < 0) {
dx = -dx;
}
}
setInterval(desenhar, 10);
</script>
</body>
</html>| Característica | LocalStorage | SessionStorage | Cookies |
|---|---|---|---|
| Capacidade | 5-10MB | 5-10MB | 4KB |
| Persistência | Permanente | Sessão | Definida |
| Envio ao servidor | Não | Não | Sim |
| Acesso | Qualquer janela | Mesma janela | Qualquer janela |
<!DOCTYPE html>
<html>
<head>
<title>Gestor de Tarefas</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
.tarefa { background: #f4f4f4; padding: 10px; margin: 5px 0; border-radius: 5px; }
.completada { text-decoration: line-through; opacity: 0.6; }
button { background: #333; color: white; padding: 5px 10px; border: none; cursor: pointer; }
button:hover { background: #555; }
</style>
</head>
<body>
<h1>Minhas Tarefas</h1>
<input type="text" id="novaTarefa" placeholder="Nova tarefa...">
<button onclick="adicionarTarefa()">Adicionar</button>
<div id="listaTarefas"></div>
<script>
// Carregar tarefas ao iniciar
window.onload = function() {
carregarTarefas();
};
function adicionarTarefa() {
const input = document.getElementById('novaTarefa');
const tarefa = input.value.trim();
if (tarefa === '') {
alert('Por favor, escreva uma tarefa!');
return;
}
const tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
tarefas.push({
id: Date.now(),
texto: tarefa,
completada: false
});
localStorage.setItem('tarefas', JSON.stringify(tarefas));
input.value = '';
carregarTarefas();
}
function carregarTarefas() {
const tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
const lista = document.getElementById('listaTarefas');
lista.innerHTML = '';
tarefas.forEach(tarefa => {
const div = document.createElement('div');
div.className = 'tarefa' + (tarefa.completada ? ' completada' : '');
div.innerHTML = `
<input type="checkbox" ${tarefa.completada ? 'checked' : ''}
onchange="toggleTarefa(${tarefa.id})">
${tarefa.texto}
<button onclick="removerTarefa(${tarefa.id})" style="float: right;">Remover</button>
`;
lista.appendChild(div);
});
}
function toggleTarefa(id) {
const tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
const tarefa = tarefas.find(t => t.id === id);
if (tarefa) {
tarefa.completada = !tarefa.completada;
localStorage.setItem('tarefas', JSON.stringify(tarefas));
carregarTarefas();
}
}
function removerTarefa(id) {
let tarefas = JSON.parse(localStorage.getItem('tarefas') || '[]');
tarefas = tarefas.filter(t => t.id !== id);
localStorage.setItem('tarefas', JSON.stringify(tarefas));
carregarTarefas();
}
</script>
</body>
</html><!DOCTYPE html>
<html>
<head>
<title>Geolocalização Avançada</title>
<style>
#mapa { width: 100%; height: 400px; border: 1px solid #ccc; margin-top: 20px; }
.info { background: #f0f0f0; padding: 10px; margin: 10px 0; border-radius: 5px; }
</style>
</head>
<body>
<h1>Geolocalização</h1>
<button onclick="obterLocalizacao()">Obter Localização</button>
<button onclick="obterLocalizacaoContinua()">Seguir Localização</button>
<button onclick="pararLocalizacao()">Parar Seguimento</button>
<div id="info" class="info"></div>
<div id="mapa"></div>
<script>
let watchId = null;
function obterLocalizacao() {
if (navigator.geolocation) {
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
navigator.geolocation.getCurrentPosition(
mostrarPosicao,
mostrarErro,
options
);
} else {
document.getElementById("info").innerHTML = "Geolocalização não suportada.";
}
}
function obterLocalizacaoContinua() {
if (navigator.geolocation) {
const options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
};
watchId = navigator.geolocation.watchPosition(
mostrarPosicao,
mostrarErro,
options
);
}
}
function pararLocalizacao() {
if (watchId !== null) {
navigator.geolocation.clearWatch(watchId);
watchId = null;
document.getElementById("info").innerHTML += "<p>Seguimento parado.</p>";
}
}
function mostrarPosicao(posicao) {
const info = document.getElementById("info");
const latitude = posicao.coords.latitude;
const longitude = posicao.coords.longitude;
const precisao = posicao.coords.accuracy;
const altitude = posicao.coords.altitude;
const precisaoAltitude = posicao.coords.altitudeAccuracy;
const direcao = posicao.coords.heading;
const velocidade = posicao.coords.speed;
const timestamp = new Date(posicao.timestamp);
info.innerHTML = `
<h3>Informações de Localização</h3>
<p><strong>Latitude:</strong> ${latitude.toFixed(6)}°</p>
<p><strong>Longitude:</strong> ${longitude.toFixed(6)}°</p>
<p><strong>Precisão:</strong> ${precisao.toFixed(0)} metros</p>
<p><strong>Altitude:</strong> ${altitude ? altitude.toFixed(0) + ' metros' : 'Não disponível'}</p>
<p><strong>Direção:</strong> ${direcao ? direcao.toFixed(0) + '°' : 'Não disponível'}</p>
<p><strong>Velocidade:</strong> ${velocidade ? velocidade.toFixed(1) + ' m/s' : 'Não disponível'}</p>
<p><strong>Timestamp:</strong> ${timestamp.toLocaleString('pt-PT')}</p>
`;
// Mostrar no mapa (simulado)
mostrarMapa(latitude, longitude);
}
function mostrarMapa(lat, lng) {
const mapa = document.getElementById("mapa");
const mapUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${lat},${lng}&zoom=15&size=600x400&markers=${lat},${lng}&key=YOUR_API_KEY`;
mapa.innerHTML = `
<h3>Mapa da Localização</h3>
<p>Latitude: ${lat.toFixed(6)}, Longitude: ${lng.toFixed(6)}</p>
<p>(Em produção, isto mostraria um mapa real)</p>
<iframe
width="100%"
height="400"
frameborder="0"
scrolling="no"
marginheight="0"
marginwidth="0"
src="https://www.openstreetmap.org/export/embed.html?bbox=${lng-0.01},${lat-0.01},${lng+0.01},${lat+0.01}&layer=mapnik&marker=${lat},${lng}">
</iframe>
`;
}
function mostrarErro(erro) {
let mensagem = "";
switch(erro.code) {
case erro.PERMISSION_DENIED:
mensagem = "Utilizador negou o pedido de Geolocalização.";
break;
case erro.POSITION_UNAVAILABLE:
mensagem = "Informação de localização indisponível.";
break;
case erro.TIMEOUT:
mensagem = "O pedido para obter a localização expirou.";
break;
case erro.UNKNOWN_ERROR:
mensagem = "Ocorreu um erro desconhecido.";
break;
}
document.getElementById("info").innerHTML = `<p style="color: red;">Erro: ${mensagem}</p>`;
}
</script>
</body>
</html>{
"name": "Minha App Offline",
"short_name": "AppOffline",
"description": "Uma aplicação que funciona offline",
"start_url": "/index.html",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}<!DOCTYPE html>
<html lang="pt-PT" manifest="cache.manifest">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>App Offline</title>
<link rel="manifest" href="manifest.json">
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
text-align: center;
}
.online { color: green; }
.offline { color: red; }
button {
padding: 10px 20px;
margin: 10px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Aplicação Offline</h1>
<div id="estado"></div>
<div id="conteudo">
<h2>Conteúdo Principal</h2>
<p>Esta aplicação funciona mesmo sem ligação à internet!</p>
<button onclick="guardarDados()">Guardar Dados Localmente</button>
<button onclick="recuperarDados()">Recuperar Dados</button>
<div id="resultado"></div>
</div>
<script>
// Detectar estado da ligação
function atualizarEstado() {
const estado = document.getElementById('estado');
if (navigator.onLine) {
estado.innerHTML = '<p class="online">✓ Online</p>';
} else {
estado.innerHTML = '<p class="offline">✗ Offline</p>';
}
}
// Atualizar estado quando a ligação muda
window.addEventListener('online', atualizarEstado);
window.addEventListener('offline', atualizarEstado);
// Estado inicial
atualizarEstado();
// Guardar dados localmente
function guardarDados() {
const dados = {
timestamp: new Date().toISOString(),
dados: 'Informação importante',
versao: '1.0'
};
localStorage.setItem('dadosApp', JSON.stringify(dados));
document.getElementById('resultado').innerHTML = '<p>Dados guardados com sucesso!</p>';
}
// Recuperar dados
function recuperarDados() {
const dadosGuardados = localStorage.getItem('dadosApp');
if (dadosGuardados) {
const dados = JSON.parse(dadosGuardados);
document.getElementById('resultado').innerHTML = `
<h3>Dados Recuperados:</h3>
<p><strong>Timestamp:</strong> ${dados.timestamp}</p>
<p><strong>Dados:</strong> ${dados.dados}</p>
<p><strong>Versão:</strong> ${dados.versao}</p>
`;
} else {
document.getElementById('resultado').innerHTML = '<p>Nenhum dado encontrado.</p>';
}
}
// Service Worker para funcionamento offline
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js')
.then(() => console.log('Service Worker registado com sucesso'))
.catch(err => console.log('Erro ao registar Service Worker:', err));
}
</script>
</body>
</html>const CACHE_NAME = 'app-offline-v1';
const urlsToCache = [
'/',
'/index.html',
'/estilos.css',
'/script.js',
'/manifest.json'
];
// Instalar Service Worker
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Cache aberto');
return cache.addAll(urlsToCache);
})
);
});
// Interceptar pedidos
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// Devolver do cache ou fazer pedido à rede
return response || fetch(event.request);
})
);
});
// Actualizar Service Worker
self.addEventListener('activate', event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});CACHE MANIFEST
# v1.0 - 2024-01-15
CACHE:
index.html
estilos.css
script.js
imagens/logo.png
imagens/fundo.jpg
NETWORK:
*
FALLBACK:
/ offline.html<!-- ✓ Correcto -->
<article>
<header>
<h1>Título do artigo</h1>
<p>Publicado em <time datetime="2024-01-15">15 de Janeiro</time></p>
</header>
<p>Conteúdo do artigo...</p>
</article>
<!-- ✗ Incorrecto -->
<div class="artigo">
<div class="cabecalho">
<div class="titulo">Título do artigo</div>
</div>
<div class="conteudo">Conteúdo do artigo...</div>
</div><!-- Imagens com texto alternativo -->
<img src="grafico-vendas.jpg" alt="Gráfico mostrando aumento de 20% nas vendas em 2024">
<!-- Formulários com labels -->
<label for="email">Email:</label>
<input type="email" id="email" name="email" required aria-describedby="email-ajuda">
<div id="email-ajuda">Introduza o seu endereço de email</div>
<!-- Navegação por teclado -->
<button onclick="funcao()" onkeypress="funcao()">Clique ou pressione Enter</button><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Descrição breve e relevante da página (150-160 caracteres)">
<meta name="keywords" content="palavras-chave, relevantes, para, a, página">
<meta name="author" content="Nome do autor">
<meta property="og:title" content="Título da página para redes sociais">
<meta property="og:description" content="Descrição para redes sociais">
<meta property="og:image" content="https://exemplo.com/imagem.jpg">
<meta property="og:url" content="https://exemplo.com/pagina">
<title>Título da página - Nome do Site</title>
<link rel="canonical" href="https://exemplo.com/pagina">
</head><!-- Imagens otimizadas -->
<img src="imagem.webp"
srcset="imagem-400.webp 400w, imagem-800.webp 800w, imagem-1200.webp 1200w"
sizes="(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px"
alt="Descrição da imagem"
loading="lazy">
<!-- CSS crítico inline -->
<style>
/* Estilos críticos para o conteúdo acima da dobra */
body { margin: 0; font-family: Arial, sans-serif; }
header { background: #333; color: white; }
</style>
<!-- CSS não-crítico carregado assincronamente -->
<link rel="preload" href="estilos.css" as="style" onload="this.onload=null;this.rel='stylesheet'"><!-- Formulários com proteção CSRF -->
<form action="/submeter" method="POST">
<input type="hidden" name="csrf_token" value="token_unico_aqui">
<!-- resto do formulário -->
</form>
<!-- Links externos com segurança -->
<a href="https://externo.com" target="_blank" rel="noopener noreferrer">Link externo</a>
<!-- Conteúdo de terceiros com sandbox -->
<iframe src="https://externo.com" sandbox="allow-scripts allow-same-origin"></iframe><!-- Use o validador online em: https://validator.w3.org/ -->
<!-- Ou instale extensões para o seu editor -->// Console para verificar erros
console.log('Mensagem de debug');
console.error('Erro detectado');
console.warn('Aviso');
// Verificar performance
console.time('operacao');
// código a medir
console.timeEnd('operacao');<!-- Execute auditorias de:
- Performance
- Acessibilidade
- Boas práticas
- SEO
- PWA
--><!DOCTYPE html>
<html>, <head>, <title>, <meta>, <link>, <style>, <script>, <body><header>, <nav>, <main>, <article>, <section>, <aside>, <footer>, <address><p>, <hr>, <pre>, <blockquote>, <ol>, <ul>, <li>, <dl>, <dt>, <dd>, <figure>, <figcaption>, <div><a>, <em>, <strong>, <small>, <s>, <cite>, <q>, <dfn>, <abbr>, <ruby>, <rt>, <rp>, <data>, <time>, <code>, <var>, <samp>, <kbd>, <sub>, <sup>, <i>, <b>, <u>, <mark>, <span>, <br>, <wbr><img>, <audio>, <video>, <source>, <track>, <canvas>, <svg><table>, <caption>, <colgroup>, <col>, <tbody>, <thead>, <tfoot>, <tr>, <td>, <th><form>, <fieldset>, <legend>, <label>, <input>, <button>, <select>, <datalist>, <optgroup>, <option>, <textarea>, <output>, <progress>, <meter><details>, <summary>, <dialog>, <menu><script>, <noscript>, <template>, <slot>, <canvas>accesskey, class, contenteditable, data-*, dir, draggable, hidden, id, lang, spellcheck, style, tabindex, title, translatetext, password, email, url, tel, search, number, range, date, month, week, time, datetime-local, color, file, checkbox, radio, submit, reset, button, image, hidden