Desenvolvimento
Guia de Desenvolvimento
Atualize a documentação apenas em website/docs (Inglês). As traduções em website/i18n/<locale>/… são geradas e não devem ser editadas manualmente. Use as tarefas de tradução (por exemplo, make translate_web_docs_batch) para atualizar o conteúdo localizado.
Pré-requisitos
- Node.js 22+ e npm (testado com Node 22)
- Thunderbird 128 ESR ou mais recente (para testes manuais)
Estrutura do Projeto (alto nível)
- Raiz: script de empacotamento
distribution_zip_packer.sh, docs, screenshots sources/: código principal do add‑on (background, UI de opções/popup, manifests, ícones)tests/: suite Vitestwebsite/: docs Docusaurus (com i18n emwebsite/i18n/de/...)
Instalação e Ferramentas
- Instalar deps na raiz:
npm ci - Docs (opcional):
cd website && npm ci - Descobrir alvos:
make help
Desenvolvimento ao vivo (web‑ext run)
- Ciclo rápido no Firefox Desktop (apenas smoke tests de UI):
npx web-ext run --source-dir sources --target=firefox-desktop- Executar no Thunderbird (preferido para MailExtensions):
npx web-ext run --source-dir sources --start-url about:addons --firefox-binary "$(command -v thunderbird || echo /path/to/thunderbird)"- Dicas:
- Mantenha a Consola de Erros do Thunderbird aberta (Tools → Developer Tools → Error Console).
- As páginas de eventos MV3 são suspensas quando inativas; recarregue o add‑on após alterações de código ou deixe o web‑ext recarregar automaticamente.
- Alguns comportamentos exclusivos do Firefox diferem; verifique sempre no Thunderbird para garantir paridade de API.
- Caminhos do binário do Thunderbird (exemplos):
- Linux:
thunderbird(por exemplo,/usr/bin/thunderbird) - macOS:
/Applications/Thunderbird.app/Contents/MacOS/thunderbird - Windows:
"C:\\Program Files\\Mozilla Thunderbird\\thunderbird.exe" - Isolamento de perfil: Use um perfil separado do Thunderbird para desenvolvimento para evitar impactar a sua configuração diária.
Alvos do Make (Alfabético)
O Makefile padroniza fluxos comuns de desenvolvimento. Execute make help a qualquer momento para um resumo em uma linha de cada alvo.
Dica: executar make sem alvo abre um menu Whiptail simples para escolher um alvo.
| Target | Descrição em uma linha |
|---|---|
clean | Remove artefactos locais de build/preview (tmp/, web-local-preview/, website/build/). |
commit | Formata, executa testes (incl. i18n), atualiza changelog, faz commit e push. |
eslint | Executa ESLint via configuração flat (npm run -s lint:eslint). |
help | Lista todos os alvos com docs de uma linha (ordenados). |
lint | web‑ext lint em sources/ (manifesto temporário; ignora ZIPs; não fatal). |
menu | Menu interativo para selecionar um alvo e argumentos opcionais. |
pack | Constrói ZIPs ATN e LOCAL (executa o linter; chama o script de empacotamento). |
prettier | Formata o repositório no local (escreve alterações). |
prettier_check | Prettier em modo verificação (sem escrita); falha se precisar de reformatar. |
prettier_write | Alias para prettier. |
test | Prettier (escrever), ESLint e depois Vitest (cobertura se configurada). |
test_i18n | Testes apenas de i18n: placeholders/paridade do add‑on + paridade do website. |
translate_app | Alias para translation_app. |
translation_app | Traduz strings da UI da app a partir de sources/_locales/en/messages.json. |
translate_web_docs_batch | Traduz docs do website via OpenAI Batch API (preferido). |
translate_web_docs_sync | Traduz docs do website de forma síncrona (legado, sem batch). |
translate_web_index | Alias para translation_web_index. |
translation_web_index | Traduz UI da homepage/navbar/footer (website/i18n/en/code.json → .../<lang>/code.json). |
web_build | Constrói docs para website/build (suporta --locales / BUILD_LOCALES). |
web_build_linkcheck | Verificação de links segura offline (ignora HTTP[S] remotos). |
web_build_local_preview | Pré‑visualização local de gh‑pages; serve automaticamente em 8080–8090; testes/link‑check opcionais. |
web_push_github | Faz push de website/build para a branch gh-pages. |
Syntax for options
- Use
make <command> OPTS="…"para passar opções (recomenda‑se aspas). Cada alvo abaixo mostra uso de exemplo.
--
Dicas de compilação de locale
- Construir um subconjunto de locales: defina
BUILD_LOCALES="en de"ou passeOPTS="--locales en,de"para os alvos web. - Pré‑visualizar um locale específico:
http://localhost:<port>/Thunderbird-Reply-with-Attachments/de/.
Compilar e Empacotar
- Construir ZIPs:
make pack - Produz ZIPs ATN e LOCAL na raiz do repositório (não edite artefactos à mão)
- Dica: atualize a versão em
sources/manifest_ATN.jsonesources/manifest_LOCAL.jsonantes de empacotar - Instalação manual (dev): Thunderbird → Tools → Add‑ons and Themes → gear → Install Add‑on From File… → selecione o ZIP gerado
Testes
- Suíte completa:
make test(Vitest) - Cobertura (opcional):
npm i -D @vitest/coverage-v8- Execute
make test; abracoverage/index.htmlpara o relatório HTML - Apenas i18n:
make test_i18n(chaves/placeholders/títulos da UI + paridade por locale/por doc do website com verificações de id/title/sidebar_label)
Depuração e Logs
- Consola de Erros: Tools → Developer Tools → Error Console
- Alternar logs verbosos em runtime:
- Ativar:
messenger.storage.local.set({ debug: true }) - Desativar:
messenger.storage.local.set({ debug: false }) - Os logs aparecem ao compor/enviar respostas
Documentação (website)
- Servidor de desenvolvimento:
cd website && npm run start - Construir site estático:
cd website && npm run build - Equivalentes no Make (alfabético):
make web_build,make web_build_linkcheck,make web_build_local_preview,make web_push_github - Exemplos de uso:
- Apenas EN, pular testes/verificação de links, sem push:
make web_build_local_preview OPTS="--locales en --no-test --no-link-check --dry-run" - Todos os locales, com testes/verificação de links, depois push:
make web_build_local_preview && make web_push_github - Antes de publicar, execute a verificação de links segura offline:
make web_build_linkcheck. - i18n: o inglês vive em
website/docs/*.md; traduções em alemão emwebsite/i18n/de/docusaurus-plugin-content-docs/current/*.md - Pesquisa: Se as variáveis de ambiente do Algolia DocSearch estiverem definidas no CI (
DOCSEARCH_APP_ID,DOCSEARCH_API_KEY,DOCSEARCH_INDEX_NAME), o site usa a pesquisa Algolia; caso contrário, reverte para a pesquisa local. Na página inicial, prima/ouCtrl+Kpara abrir a caixa de pesquisa.
Rota de redirecionamento de doação
website/src/pages/donate.js- Rota:
/donate(e/<locale>/donate) - Comportamento:
- Se a rota atual tiver um locale (por exemplo,
/de/donate), use‑o - Caso contrário, escolha a melhor correspondência de
navigator.languagesvs locales configurados; caso falhe, use o locale por omissão - Redireciona para:
en→/docs/donation- outros →
/<locale>/docs/donation - Usa
useBaseUrlpara tratar corretamente o baseUrl - Inclui meta refresh + link
noscriptcomo alternativa
Dicas de pré‑visualização
- Pare a pré‑visualização do Node de forma limpa: abra
http://localhost:<port>/__stop(impresso apósLocal server started). - Se as imagens não carregarem em MDX/JSX, use
useBaseUrl('/img/...')para respeitar obaseUrldo site. - O preview inicia primeiro; a verificação de links executa depois e não é bloqueante (links externos quebrados não impedem o preview).
- URL de preview de exemplo:
http://localhost:<port>/Thunderbird-Reply-with-Attachments/(impresso após “Local server started”). - Links externos na verificação: Alguns sites externos (por exemplo, addons.thunderbird.net) bloqueiam crawlers automatizados e podem mostrar 403 nas verificações. O preview ainda inicia; é seguro ignorar.
Traduzir o Website
O que pode traduzir
- Apenas a UI do website: página inicial, barra de navegação, rodapé e outras strings de UI. O conteúdo das docs permanece apenas em inglês por agora.
Onde editar
- Edite
website/i18n/<locale>/code.json(useencomo referência). Mantenha placeholders como{year},{slash},{ctrl},{k},{code1}inalterados.
Gerar ou atualizar ficheiros
- Criar stubs em falta para todos os locales:
npm --prefix website run i18n:stubs - Sobrescrever stubs a partir do inglês (após adicionar novas strings):
npm --prefix website run i18n:stubs:force - Alternativa para um único locale:
npx --prefix website docusaurus write-translations --locale <locale>
Traduzir strings de UI da homepage/navbar/footer (OpenAI)
- Defina as credenciais uma vez (shell ou .env):
export OPENAI_API_KEY=sk-...- Opcional:
export OPENAI_MODEL=gpt-4o-mini - De uma só vez (todos os locales, ignorando en):
make translate_web_index - Limitar a locales específicos:
make translate_web_index OPTS="--locales de,fr" - Sobrescrever valores existentes:
make translate_web_index OPTS="--force"
Validação e retentativas
- O script de tradução valida a estrutura do JSON, preserva placeholders entre chavetas e garante que os URLs permanecem inalterados.
- Em caso de falha de validação, tenta novamente com feedback até 2 vezes antes de manter os valores existentes.
Pré‑visualize o seu locale
- Servidor de desenvolvimento:
npm --prefix website run start - Visite
http://localhost:3000/<locale>/Thunderbird-Reply-with-Attachments/
Submissão
- Abra um PR com o(s) ficheiro(s)
code.jsoneditado(s). Mantenha as alterações focadas e inclua uma captura de ecrã rápida quando possível.
Dicas de Segurança e Configuração
- Não faça commit de
sources/manifest.json(criado temporariamente pelo build) - Mantenha
browser_specific_settings.gecko.idestável para preservar o canal de atualização
Persistência das Definições
- Armazenamento: Todas as definições do utilizador residem em
storage.locale persistem entre atualizações do add‑on. - Instalação: Os valores por omissão são aplicados apenas quando uma chave está estritamente em falta (undefined).
- Atualização: Uma migração preenche apenas chaves em falta; os valores existentes nunca são sobrescritos.
- Marcador de esquema:
settingsVersion(atualmente1). - Chaves e valores por omissão:
blacklistPatterns: string[]→['*intern*', '*secret*', '*passwor*']confirmBeforeAdd: boolean→falseconfirmDefaultChoice: 'yes'|'no'→'yes'warnOnBlacklistExcluded: boolean→true- Código: ver
sources/background.js→initializeOrMigrateSettings()eSCHEMA_VERSION.
Fluxo de desenvolvimento (adicionando uma nova definição)
- Aumente
SCHEMA_VERSIONemsources/background.js. - Adicione a nova chave + valor por omissão ao objeto
DEFAULTSeminitializeOrMigrateSettings(). - Use a regra "only-if-undefined" ao definir valores por omissão; não sobrescreva valores existentes.
- Se a definição for visível para o utilizador, integre‑a em
sources/options.jse adicione strings localizadas. - Adicione/ajuste testes (ver
tests/background.settings.migration.test.js).
Dicas para testes manuais
- Simular uma instalação limpa: limpe o diretório de dados da extensão ou inicie com um novo perfil.
- Simular uma atualização: defina
settingsVersionpara0emstorage.locale recarregue; confirme que os valores existentes permanecem inalterados e apenas chaves em falta são adicionadas.
Resolução de Problemas
- Certifique‑se de que o Thunderbird é 128 ESR ou mais recente
- Use a Consola de Erros para problemas de runtime
- Se as definições armazenadas parecerem não se aplicar corretamente, reinicie o Thunderbird e tente novamente. (O Thunderbird pode manter estado em cache entre sessões; um reinício garante que as definições novas são carregadas.)
CI e Cobertura
- O GitHub Actions (
CI — Tests) executa o vitest com limites de cobertura (85% linhas/funções/ramificações/declarações). Se os limites não forem cumpridos, o job falha. - O workflow carrega um artefacto
coverage-htmlcom o relatório HTML; transfira‑o a partir da página da execução (Actions → execução mais recente → Artifacts).
Contribuição
- Veja CONTRIBUTING.md para diretrizes de branch/commit/PR
- Dica: Crie um perfil de desenvolvimento do Thunderbird separado para testes a fim de evitar impactar o seu perfil diário.
Traduções
- Executar tarefas grandes de tradução “all → all” pode ser lento e caro. Comece com um subconjunto (por exemplo, alguns documentos e 1–2 locales), reveja o resultado e depois expanda.
- Política de retentativas: tarefas de tradução executam até 3 retentativas com backoff exponencial em erros da API; veja
scripts/translate_web_docs_batch.jsescripts/translate_web_docs_sync.js.
Capturas de ecrã para a documentação
-
Guarde as imagens em
website/static/img/. -
Referencie-as em MD/MDX via
useBaseUrl('/img/<filename>')para que os caminhos funcionem com obaseUrldo site. -
Após adicionar ou renomear imagens em
website/static/img/, confirme que todas as referências ainda usamuseBaseUrl('/img/…')e renderizam numa pré‑visualização local. Favicons -
O
favicon.icomulti‑tamanho é gerado automaticamente em todos os caminhos de build (Make + scripts) viawebsite/scripts/build-favicon.mjs. -
Não é necessário nenhum passo manual; atualizar
icon-*.pngé suficiente. Dica de revisão -
Mantenha o front‑matter
idinalterado em docs traduzidas; traduza apenastitleesidebar_labelquando presentes.
clean
- Finalidade: remover artefactos locais de build/preview.
- Uso:
make clean - Remove (se existirem):
tmp/web-local-preview/website/build/
commit
- Finalidade: formatar, testar, atualizar changelog, fazer commit e push.
- Uso:
make commit - Detalhes: executa Prettier (escrever),
make test,make test_i18n; anexa o changelog quando há diffs em stage; faz push paraorigin/<branch>.
eslint
- Finalidade: executar o ESLint via configuração flat.
- Uso:
make eslint
help
- Finalidade: listar todos os alvos com docs de uma linha.
- Uso:
make help
lint
- Finalidade: fazer lint da MailExtension usando
web-ext. - Uso:
make lint - Notas: copia temporariamente
sources/manifest_LOCAL.json→sources/manifest.json; ignora ZIPs; avisos não falham o pipeline.
menu
- Finalidade: menu interativo para selecionar um alvo do Make e argumentos opcionais.
- Uso: execute
makesem argumentos. - Notas: se
whiptailnão estiver disponível, o menu recua paramake help.
pack
- Finalidade: construir ZIPs ATN e LOCAL (depende de
lint). - Uso:
make pack - Dica: incremente as versões em
sources/manifest_*.jsonantes de empacotar.
prettier
- Finalidade: formatar o repositório no local.
- Uso:
make prettier
prettier_check
- Finalidade: verificar formatação (sem escrita).
- Uso:
make prettier_check
prettier_write
- Finalidade: alias para
prettier. - Uso:
make prettier_write
test
- Finalidade: executar Prettier (escrever), ESLint e depois Vitest (cobertura se instalada).
- Uso:
make test
test_i18n
- Finalidade: testes focados em i18n para strings do add‑on e docs do website.
- Uso:
make test_i18n - Executa:
npm run test:i18nenpm run -s test:website-i18n.
translate_app / translation_app
- Finalidade: traduzir strings de UI do add‑on de EN para outros locales.
- Uso:
make translation_app OPTS="--locales all|de,fr" - Notas: preserva a estrutura das chaves e placeholders; regista em
translation_app.log. Forma de script:node scripts/translate_app.js --locales ….
translate_web_docs_batch / translate_web_docs_sync
- Finalidade: traduzir docs do website de
website/docs/*.mdparawebsite/i18n/<locale>/.... - Preferido:
translate_web_docs_batch(OpenAI Batch API)- Uso (flags):
make translate_web_docs_batch OPTS="--files <doc1,doc2|all> --locales <lang1,lang2|all>" - O posicional legado ainda é aceite:
OPTS="<doc|all> <lang|all>"
- Uso (flags):
- Comportamento: constrói JSONL, carrega, verifica a cada 30s, transfere resultados, escreve ficheiros.
- Nota: um job em batch pode demorar até 24 horas para concluir (conforme a janela de batch da OpenAI). A consola mostra o tempo decorrido a cada verificação.
- Ambiente:
OPENAI_API_KEY(obrigatório), opcionalOPENAI_MODEL,OPENAI_TEMPERATURE,OPENAI_BATCH_WINDOW(predefinição 24h),BATCH_POLL_INTERVAL_MS. - Legado:
translate_web_docs_sync- Uso (flags):
make translate_web_docs_sync OPTS="--files <doc1,doc2|all> --locales <lang1,lang2|all>" - O posicional legado ainda é aceite:
OPTS="<doc|all> <lang|all>"
- Uso (flags):
- Comportamento: pedidos síncronos por par (sem agregação em batch).
- Notas: Prompts interativos quando
OPTSé omitido. Ambos os modos preservam blocos de código/código inline e mantêm o front‑matteridinalterado; regista emtranslation_web_batch.log(batch) outranslation_web_sync.log(sync).
translate_web_index / translation_web_index
- Finalidade: traduzir strings de UI do website (homepage, navbar, footer) de
website/i18n/en/code.jsonpara todos os locales emwebsite/i18n/<locale>/code.json(excluindoen). - Uso:
make translate_web_indexoumake translate_web_index OPTS="--locales de,fr [--force]" - Requisitos: exportar
OPENAI_API_KEY(opcional:OPENAI_MODEL=gpt-4o-mini). - Comportamento: valida a estrutura JSON, preserva placeholders entre chavetas, mantém URLs inalterados e faz novas tentativas com feedback em erros de validação.
web_build
- Finalidade: construir o site de docs para
website/build. - Uso:
make web_build OPTS="--locales en|de,en|all"(ou definaBUILD_LOCALES="en de") - Internos:
node ./node_modules/@docusaurus/core/bin/docusaurus.mjs build [--locale …]. - Dependências: executa
npm ciemwebsite/apenas sewebsite/node_modules/@docusaurusestiver em falta.
web_build_linkcheck
- Finalidade: verificação de links segura offline.
- Uso:
make web_build_linkcheck OPTS="--locales en|all" - Notas: constrói para
tmp_linkcheck_web_pages; reescrevebaseUrldo GH Pages para/; ignora links HTTP(S) remotos.
web_build_local_preview
- Finalidade: pré‑visualização local de gh‑pages com testes/link‑check opcionais.
- Uso:
make web_build_local_preview OPTS="--locales en|all [--no-test] [--no-link-check] [--dry-run] [--no-serve]" - Comportamento: tenta primeiro o servidor de pré‑visualização em Node (
scripts/preview-server.mjs, suporta/__stop), recua parapython3 -m http.server; serve em 8080–8090; PID emweb-local-preview/.server.pid.
web_push_github
- Finalidade: fazer push de
website/buildpara a branchgh-pages. - Uso:
make web_push_github
Dica: defina NPM=… para substituir o gestor de pacotes usado pelo Makefile (predefinido: npm).