- TypeScript 77%
- Shell 9.8%
- CSS 8%
- HTML 4.7%
- JavaScript 0.5%
| .gitea/workflows | ||
| docs | ||
| protocols | ||
| public | ||
| scripts | ||
| src | ||
| tests | ||
| .gitignore | ||
| biome.json | ||
| commitlint.config.cjs | ||
| DESIGN.md | ||
| lefthook.yml | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
| wxt.config.ts | ||
Carbon Copy
Extensión de Greasy Sprocket para Gmail: reglas que añaden destinatarios en Cc y Cco mientras escribes. Sin cuenta, sin servidor, sin telemetría y sin premium.
La alternativa comercial habitual cobra por esto y, cuando caduca la prueba, deja las
reglas guardadas pero inertes. Aquí las reglas son tuyas, viven en chrome.storage y
la extensión hace una sola cosa.
Qué hace
Creas reglas del tipo:
- cuando el dominio del destinatario es
cliente.com - cuando un destinatario exacto es
ana@cliente.com - cuando el asunto contiene
factura
y cada regla añade una o más direcciones a Cc y/o a Cco. Todas las reglas activas que casan se acumulan, sin duplicados.
Tres detalles de comportamiento que son deliberados:
- Solo añade, nunca quita. Si ya has puesto una dirección a mano, no se toca.
- Si borras un chip que puso la extensión, no vuelve. Ese compositor recuerda la dirección como eliminada mientras siga abierto.
- Nunca envía. Rellena la ventana de redacción y tú pulsas Enviar.
Cómo funciona
src/lib/rules.ts es el modelo puro (condiciones, validación, acumulación).
src/lib/gmail-compose.ts traduce eso al DOM de Gmail: localiza ventanas de redacción por
[contenteditable][role="textbox"] + input[name="subjectbox"], clasifica los campos de
destinatarios por su aria-label (inglés y español) y escribe la dirección con el setter
nativo de HTMLInputElement seguido de Enter, que es como Gmail convierte el texto en chip.
El content script corre solo en https://mail.google.com/*, observa mutaciones con debounce
y añade una dirección por campo y pasada: Gmail crea el chip de forma asíncrona y escribir
la siguiente dirección antes de tiempo produce un único chip con texto separado por comas.
Limitaciones conocidas (honestas)
- Depende del DOM de Gmail. No hay API que permita inyectar Cc/Cco al enviar desde la web;
esto es lo mismo que hacen las extensiones de esta categoría. Si Google cambia los
aria-labelo el botón Cc/Bcc, hay que actualizar los selectores. El código degrada a "no hacer nada" en vez de escribir en el campo equivocado. - Los campos Cc/Cco tienen que poder revelarse. Si Gmail cambia el enlace "Cc"/"Cco" por
otro control,
openFieldno lo encuentra y no se añade nada. - Gmail en otros idiomas: los
aria-labelse reconocen en inglés y español. Añadir un idioma es añadir sus etiquetas aclassifyLabely a la lista de disparadores. - Sin verificación contra una cuenta real en este repo. Los tests cubren el modelo y el DOM con jsdom; la prueba end-to-end en Gmail la hace una persona antes de publicar.
Permisos
storage— guardar las reglas (consync, fallback alocal).sidePanel— la interfaz.https://mail.google.com/*— el content script; la extensión no lee ni envía el correo, solo la ventana de redacción.
Desarrollo
pnpm install
pnpm wxt prepare
pnpm run validate # typecheck + lint + tests + gates de diseño y sidepanel
pnpm build
bash scripts/build-zip.sh
En este host no hay node: se construye en docker run node:24-bookworm con el store en un
volumen (-v gs-pnpm-store:/store).
Release
- Subir
versionenpackage.json(una sola fuente; no hay literal enwxt.config.ts). pnpm run validateybash scripts/build-zip.sh.- Publicar el ZIP y verificar el manifest dentro del ZIP contra el tag.
- Añadir
update_urlenwxt.config.tscuando la Chrome Web Store asigne el id.
Sin bump no hay release: Chrome ignora una versión que ya ha visto.