Este tutorial cria o menor protótipo útil do Chrome Manifest V3: uma área de texto privada montada nas páginas do Pinterest Pin, codificada pelo ID numérico do Pin e salva em chrome.storage.local. É intencionalmente um protótipo, não um clone pronto para produção das notas anteriores do Pinterest.
O DOM do Pinterest pode mudar sem aviso prévio. Mantenha os seletores isolados, evite imitar a marca protegida do Pinterest e teste os tipos de páginas e localidades que você oferece suporte.
1. Crie a extensão Manifest V3
Crie uma pasta com manifesto.json e conteúdo.js. do cromo referência de manifesto é a fonte da verdade para as chaves disponíveis.
{
"versão_manifesto": 3,
"name": "Protótipo de contexto de pino",
"versão": "0.1.0",
"description": "Salvar uma nota local privada para um Pin do Pinterest.",
"permissões": ["armazenamento"],
"content_scripts": [{
"correspondências": ["https://*.pinterest.com/*"],
"js": ["content.js"],
"run_at": "documento_idle"
}]
}
A correspondência do host é ampla porque o Pinterest usa navegação do lado do cliente. Se o seu recurso oferece suporte a menos rotas ou domínios de países, restrinja e documente esse escopo.
2. Obtenha uma chave estável do URL do Pin
Não digite notas pela posição de um cartão ou título visível. Extraia o ID numérico de um canônico /pino/…/ caminho e retorno nulo em todos os outros lugares.
função getPinId (url = localização.href) {
tente {
const {nome do caminho} = novo URL(url);
const match = pathname.match(//pin/(d+)/?/);
partida de retorno? correspondência[1]: nulo;
} pegar {
retornar nulo;
}
}
Teste URLs detalhados válidos, strings de consulta, páginas não-Pin, URLs malformados e quaisquer padrões de localidade que você afirma oferecer suporte. Nunca anexe uma nota silenciosamente quando a identificação for incerta.
3. Armazene um registro versionado
Mantenha o esquema explícito para que futuras migrações sejam possíveis:
função assíncrona readNote(pinId) {
const key = 'pin-nota:' + pinId;
resultado const = aguarda chrome.storage.local.get(chave);
retornar resultado[chave] ?? { versão: 1, pinId, texto: '', atualizadoAt: null };
}
função assíncrona writeNote(pinId, texto) {
const key = 'pin-nota:' + pinId;
registro constante = {
versão: 1,
PINId,
texto,
atualizadoAt: new Date().toISOString()
};
aguarde chrome.storage.local.set({ [chave]: registro });
registro de retorno;
}
O Chrome documenta um limite padrão de 10 MB para armazenamento.local, com um separado armazenamento ilimitado permissão para aumentá-lo. O Chrome também documenta que o armazenamento local da extensão é limpo quando a extensão é removida. Leia o atual Documentação da API de armazenamento e exporte o design antes de solicitar dados importantes.
4. Monte um editor isolado e acessível
Um Shadow DOM reduz colisões acidentais de estilo. O exemplo é anexado ao corpo da página para que não dependa de um nome de classe frágil do Pinterest:
função assíncrona mountEditor(pinId) {
if (document.querySelector('[data-pin-context-root]')) retorno;
const host = document.createElement('aside');
host.dataset.pinContextRoot = '';
host.setAttribute('aria-label', 'Nota do Pin Privado');
document.body.append(host);
const root = host.attachShadow({modo: 'aberto' });
rótulo const = document.createElement('rótulo');
label.textContent = 'Nota privada';
editor const = document.createElement('textarea');
editor.setAttribute('aria-label', 'Nota privada para este Pin');
const status = document.createElement('span');
status.setAttribute('role', 'status');
const salvo = aguarda readNote(pinId);
editor.valor = salvo.texto;
root.append(rótulo, editor, status);
bindAutosave(editor, status, pinId);
}
Crie texto de interface com textoConteúdo, não confiável HTML interno. Adicione estilos de foco visíveis, contraste suficiente, um rótulo real, acesso ao teclado e texto de status que não roube o foco.
5. Salve sem escrever a cada pressionamento de tecla
function bindAutosave(editor, status, pinId) {
deixe salvarTimer;
editor.addEventListener('input', () => {
status.textContent = 'Não salvo';
clearTimeout(saveTimer);
saveTimer = setTimeout(async() => {
tente {
aguarde writeNote(pinId, editor.value);
status.textContent = 'Salvo localmente';
} pegar (erro) {
console.error('Falha ao salvar nota de fixação', erro);
status.textContent = 'Não foi possível salvar';
}
}, 400);
});
}
Para produção, libere também entradas pendentes na transição de página, proteja-se contra duas guias que se sobrepõem, defina um tamanho máximo de nota e detecte erros de cota.
6. Lide com a navegação do lado do cliente do Pinterest
Um manipulador de carregamento de página único perde a navegação entre as visualizações de feed e de detalhes. Use uma função de reconciliação idempotente e observe as alterações sem remontar a cada mutação:
deixe agendado = falso;
função assíncrona reconciliar() {
agendado = falso;
const pinId = getPinId();
const existente = document.querySelector('[data-pin-context-root]');
se (!pinId) {
existente?.remove();
retornar;
}
if (existente?.dataset.pinId === pinId) return;
existente?.remove();
aguarde mountEditor(pinId);
const montado = document.querySelector('[data-pin-context-root]');
if (montado) montado.dataset.pinId = pinId;
}
novo MutationObserver(() => {
se retorno (programado);
agendado = verdadeiro;
requestAnimationFrame(reconciliar);
}).observe(document.documentElement, { childList: true, subtree: true });
conciliar();
Uma versão de produção também deve observar o estado de navegação diretamente, sempre que possível, e desconectar os observadores de que não precisa mais. Crie o perfil do código em feeds longos; um recurso correto que degrada o desempenho da página ainda é uma extensão ruim.
7. Respeite as restrições de segurança do Manifest V3
O Manifest V3 proíbe código executável hospedado remotamente. Agrupe o JavaScript executável com a extensão, mantenha a política de segurança de conteúdo padrão, a menos que você tenha uma alteração justificada, evite a execução dinâmica de código e solicite apenas as permissões exigidas pelo recurso. do cromo Visão geral do manifesto V3 explica o modelo da plataforma.
8. Adicione os recursos que um produto real precisa
- Exportação/importação JSON com validação de esquema e tratamento de conflitos;
- exportação legível para recuperação;
- pesquisa e tags opcionais;
- relatórios de uso de armazenamento e cotas;
- exclusão por nota e para todos os dados;
- uma política de privacidade que corresponda ao comportamento observável;
- testes de migração entre versões de esquema;
- limpar avisos de desinstalação e não sincronização;
- telemetria de erros apenas com minimização e divulgação cuidadosas.
9. Teste os caminhos de falha
- Carregue a extensão descompactada de
cromo://extensões. - Visite um feed, um quadro, uma página de detalhes do Pin e uma rota sem Pin.
- Navegue entre dois Pins sem recarregar e confirme o isolamento da nota.
- Abra o mesmo Pin em duas guias e teste o comportamento do conflito.
- Desative o armazenamento ou simule falha de cota e verifique o aviso.
- Exporte, remova um registro de teste e restaure-o.
- Teste a navegação do teclado, o zoom, os rótulos do leitor de tela e as condições de página escura/clara.
A lição de engenharia
A área de texto é a parte fácil. Uma extensão confiável do Pinterest depende de identidade estável, gerenciamento resiliente do ciclo de vida, interface de usuário acessível, permissões restritas, armazenamento documentado e um caminho de saída testado. Desenvolva essas qualidades antes de expandir a lista de recursos.
Continue construindo seu sistema Pinterest
Continue com o guia que corresponde à sua próxima etapa:
Obtenha a extensão Notestopin do Chrome
Adicione notas privadas a qualquer Pin, marque-os e pesquise seus salvamentos mais tarde.
Adicionar ao Chrome