Executar scripts em todas as páginas

Crie sua primeira extensão que insira um novo elemento na página.

Informações gerais

Neste tutorial, uma extensão que adiciona o tempo de leitura esperado a qualquer extensão do Chrome e página de documentação da Chrome Web Store é criada.

Extensão de tempo de leitura na página de boas-vindas da extensão
Extensão de tempo de leitura na página de boas-vindas da extensão.

Neste guia, vamos explicar os seguintes conceitos:

  • O manifesto da extensão.
  • Quais tamanhos de ícone uma extensão usa.
  • Como injetar código em páginas usando scripts de conteúdo.
  • Como usar padrões de correspondência.
  • Permissões da extensão.

Antes de começar

Este guia pressupõe que você tenha experiência básica em desenvolvimento da Web. Recomendamos conferir o tutorial Hello World para uma introdução ao fluxo de trabalho de desenvolvimento de extensões.

Criar a extensão

Para começar, crie um novo diretório chamado reading-time para armazenar os arquivos da extensão. Se preferir, faça o download do código-fonte completo no GitHub (link em inglês).

Etapa 1: adicionar informações sobre a extensão

O arquivo JSON de manifesto é o único arquivo obrigatório. Ele contém informações importantes sobre a extensão. Crie um arquivo manifest.json na raiz do projeto e adicione o seguinte código:

{
  "manifest_version": 3,
  "name": "Reading time",
  "version": "1.0",
  "description": "Add the reading time to Chrome Extension documentation articles"
}

Essas chaves contêm metadados básicos da extensão. Eles controlam como a extensão aparece na página correspondente e, quando publicada, na Chrome Web Store. Para saber mais, confira as chaves "name", "version" e "description" na página de visão geral do Manifest.

💡 Outros fatos sobre o manifesto da extensão

  • Ele precisa estar localizado na raiz do projeto.
  • As únicas chaves obrigatórias são "manifest_version", "name" e "version".
  • A interface oferece suporte a comentários (//) durante o desenvolvimento, mas eles precisam ser removidos antes do upload do seu código para a Chrome Web Store.

Etapa 2: fornecer os ícones

Então, por que você precisa de ícones? Embora os ícones sejam opcionais durante o desenvolvimento, eles são necessários se você planeja distribuir sua extensão na Chrome Web Store. Elas também aparecem em outros lugares, como a página de gerenciamento de extensões.

Crie uma pasta images e coloque os ícones nela. Faça o download dos ícones no GitHub (em inglês). Em seguida, adicione o código destacado ao manifesto para declarar os ícones:

{
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  }
}

Recomendamos o uso de arquivos PNG, mas outros formatos são permitidos, exceto SVG.

💡 Onde esses ícones de tamanhos diferentes são exibidos?

Tamanho do ícone Uso de ícones
16x16 Favicon nas páginas e no menu de contexto da extensão.
32x32 Computadores Windows geralmente exigem esse tamanho.
48x48 Aparece na página "Extensões".
128x128 Aparece na instalação e na Chrome Web Store.

Etapa 3: declarar o script de conteúdo

As extensões podem executar scripts que leem e modificam o conteúdo de uma página. Eles são chamados de scripts de conteúdo. Eles vivem em um mundo isolado, o que significa que podem fazer alterações no ambiente JavaScript sem entrar em conflito com a página do host ou os scripts de conteúdo de outras extensões.

Adicione o seguinte código ao manifest.json para registrar um script de conteúdo chamado content.js.

{
  "content_scripts": [
    {
      "js": ["scripts/content.js"],
      "matches": [
        "https://developer.chrome.com/docs/extensions/*",
        "https://developer.chrome.com/docs/webstore/*"
      ]
    }
  ]
}

O campo "matches" pode ter um ou mais padrões de correspondência. Elas permitem que o navegador identifique em quais sites injetar os scripts de conteúdo. Os padrões de correspondência consistem em três partes: <scheme>://<host><path>. Eles podem conter caracteres "*".

💡 Esta extensão exibe um aviso de permissão?

Quando um usuário instala uma extensão, o navegador informa o que ela pode fazer. Os scripts de conteúdo solicitam permissão para execução em sites que atendem aos critérios do padrão de correspondência.

Nesse exemplo, o usuário veria o seguinte aviso de permissão:

Aviso de permissão que o usuário verá ao instalar a extensão de tempo de leitura
Aviso de permissão de tempo de leitura.

Para saber mais sobre as permissões de extensões, consulte Declarar permissões e alertar os usuários.

Etapa 4: calcular e inserir o tempo de leitura

Os scripts de conteúdo podem usar o Modelo de objeto de documentos (DOM) padrão para ler e alterar o conteúdo de uma página. A extensão verifica primeiro se a página contém o elemento <article>. Depois, a função vai contar todas as palavras nesse elemento e criar um parágrafo que mostra o tempo total de leitura.

Crie um arquivo chamado content.js dentro de uma pasta chamada scripts e adicione o seguinte código:

const article = document.querySelector("article");

// `document.querySelector` may return null if the selector doesn't match anything.
if (article) {
  const text = article.textContent;
  const wordMatchRegExp = /[^\s]+/g; // Regular expression
  const words = text.matchAll(wordMatchRegExp);
  // matchAll returns an iterator, convert to array to get word count
  const wordCount = [...words].length;
  const readingTime = Math.round(wordCount / 200);
  const badge = document.createElement("p");
  // Use the same styling as the publish information in an article's header
  badge.classList.add("color-secondary-text", "type--caption");
  badge.textContent = `⏱️ ${readingTime} min read`;

  // Support for API reference docs
  const heading = article.querySelector("h1");
  // Support for article docs with date
  const date = article.querySelector("time")?.parentNode;

  (date ?? heading).insertAdjacentElement("afterend", badge);
}

💡 JavaScript interessante usado neste código

  • Expressões regulares usadas para contar apenas as palavras dentro do elemento <article>.
  • insertAdjacentElement() usado para inserir o nó de tempo de leitura depois do elemento.
  • A propriedade classList usada para adicionar nomes de classes CSS ao atributo de classe do elemento.
  • Encadeamento opcional usado para acessar uma propriedade de objeto que pode ser indefinida ou nula.
  • A coalescência nula vai retornar a <heading> se a <date> for nula ou indefinida.

Testar se ele funciona

Verifique se a estrutura de arquivos do seu projeto é semelhante a esta:

O conteúdo da pasta de tempo de leitura: manifest.json, content.js nas pastas de scripts e de imagens.

Carregar sua extensão localmente

Para carregar uma extensão descompactada no modo de desenvolvedor, siga as etapas em Noções básicas de desenvolvimento.

Abrir uma extensão ou a documentação da Chrome Web Store

Aqui estão algumas páginas que você pode abrir para ver quanto tempo cada artigo levará para ser lido.

Ele será parecido com o seguinte:

Tempo de leitura em execução na página de boas-vindas
Página de recepção da extensão com a extensão de tempo de leitura

🎯 Possíveis melhorias

Com base no que você aprendeu hoje, tente implementar uma das seguintes opções:

  • Adicione outro padrão de correspondência ao manifest.json para oferecer compatibilidade com outras páginas de desenvolvedores do Chrome, como o Chrome DevTools ou o Workbox.
  • Adicione um novo script de conteúdo que calcule o tempo de leitura de qualquer um dos seus blogs ou sites de documentação favoritos.

Continuar criando

Parabéns por concluir este tutorial 🎉. Continue desenvolvendo suas habilidades concluindo outros tutoriais desta série:

Extensão Conteúdo do laboratório
Modo sem distrações Para executar o código na página atual depois de clicar na ação de extensão.
Gerenciador de guias Para criar um pop-up que gerencia as guias do navegador.

Continue descobrindo

Esperamos que você tenha gostado de criar essa extensão do Chrome e esteja animado para continuar sua jornada de aprendizado de desenvolvimento do Chrome. Recomendamos o programa de aprendizado a seguir: