Articles

kotachang / Word-Replacer-Chrome-Extension

¡Ven a unirte a nosotros en #hackpack-chrome-ext en Slack para obtener ayuda, pasar el rato y mostrar tu proyecto!

Descripción

¡Felicidades! Usted ha elegido este hackpack, y usted está bien en su camino a la construcción de un producto super cool!

En este hackpack, usted construirá una extensión de cromo que reemplaza el contenido en las páginas web de acuerdo a las reglas personalizables. De un vistazo, sus tareas incluirán:

  1. Reemplazar todas las instancias del texto «cal» en todas las páginas web.
  2. Reemplazar todo el texto en una página web de acuerdo con las reglas de reemplazo especificadas por el usuario.
  3. Reemplazar todas las imágenes en una página web de acuerdo con las reglas de reemplazo especificadas por el usuario.

¡Después de que haya terminado estas tareas, habrá construido una emocionante aplicación que puede utilizar en su propio navegador!

Comenzando

1. Descarga y descomprime el código de inicio.

Aproximadamente deberías tener los siguientes archivos.

hackpack-chrome-ext-master/├── README.md├── manifest.json├── icons│ ├── TreeHacks-white-128.png│ ├── TreeHacks-white-16.png│ ├── TreeHacks-white-19.png│ ├── TreeHacks-white-32.png│ ├── TreeHacks-white-48.png│ ├── TreeHacks-white-64.png│ └── TreeHacks-white-96.png└── src ├── bg │ └── background.js ├── browser_action │ ├── browser_action.css │ ├── browser_action.html │ └── browser_action.js ├── inject │ └── inject.js └── options ├── options.css ├── options.html └── options.js

Alternativamente, si eres un maestro Git, puedes sincronizar con nuestro repositorio Git a través de HTTPS o SSH. Nota: Si no estás familiarizado con Git, o no sabes lo que harían las siguientes líneas, ¡no ejecutes los siguientes comandos!

# From Terminal.app or equivalent...# Clone via HTTPS$ git clone https://github.com/TreeHacks/hackpack-chrome-ext.git# or SSH$ git clone [email protected]:TreeHacks/hackpack-chrome-ext.git

Comenzando

Descarga Google Chrome

¡Para construir una extensión de Chrome, necesitarás Google Chrome! Si aún no has descargado Chrome, descarga la última versión aquí. Para este hackpack, necesitarás la versión 40 de Chrome o más reciente. Para saber qué versión tienes, ve a chrome://version/ en la Omnibar, y mira la línea superior. Deberías ver algo como

Google Chrome48.0.2564.109 (Official Build) (64-bit)

No te preocupes si no es exactamente lo mismo. Mientras el número mayor (antes del punto decimal) sea mayor que 40, ¡estás listo!

Cargar el código de inicio

Chrome suele enviar las extensiones como archivos .crx (similares a los archivos .zip), lo cual es genial para la distribución, pero no tanto para el desarrollo. En su lugar, le diremos a Chrome que trate la carpeta de código de inicio como una extensión.

Necesitamos habilitar la configuración de desarrollador de Chrome con el fin de construir nuestra extensión de cromo.

Para hacer esto:

  1. Navega a chrome://extensiones en tu navegador.
  2. Asegúrese de que la casilla de verificación del modo desarrollador en la esquina superior derecha está marcada.
  3. Haga clic en Cargar extensión desempaquetada… para que aparezca un diálogo de selección de archivos.
  4. Navegue hasta el directorio en el que se encuentran sus archivos de extensión y selecciónelo.

Ahora debería ver una pantalla parecida a la siguiente:

Loading Starter Code

Note que la casilla de verificación del modo desarrollador está marcada y la extensión está habilitada.

Además, preste mucha atención al enlace Recargar.

Por defecto, Chrome no recargará su extensión automáticamente si actualiza su código. Por lo tanto, si quieres probar tu extensión, debes recargar la extensión antes de probarla. De lo contrario, sus cambios no estarán presentes en la extensión activa. Básicamente, cada vez que hagas un cambio en tu código que quieras probar en vivo en Chrome, asegúrate de recargar la extensión usando ese botón de Recarga.

Conocimientos previos

Para este proyecto, necesitarás algunos conocimientos de Javascript y de Extensiones de Chrome. El código de inicio debería tener suficientes comentarios para explicar cada archivo, pero si desea obtener una comprensión más profunda de estos sistemas antes de comenzar el hackpack, hemos proporcionado enlaces a algunos tutoriales a continuación. En particular, si usted nunca ha visto Javascript antes, recomendamos encarecidamente ir a través de un tutorial de Javascript.

Aprender sobre Javascript

¿Qué es JavaScript?

JavaScript es un lenguaje de scripting para ordenadores. A menudo se ejecuta en aplicaciones del navegador web para crear contenido dinámico como un mensaje emergente o un reloj en vivo. No está relacionado con el lenguaje de programación Java.

Aquí tienes algunos de nuestros tutoriales favoritos de Javascript!

Si ya eres un experto en varios lenguajes de programación, o solías conocer Javascript y sólo necesitas un repaso de la sintaxis, echa un vistazo a Aprende X en Y minutos. Este tutorial dura unos 10 minutos.

Si nunca has visto (u oído) Javascript antes, o quieres un tutorial profundo e involucrado que te lleve a través de Javascript desde el principio, recomendamos Codecademy. Este tutorial dura unas 10 horas.

Si quieres un tutorial completo de todo lo relacionado con Javascript, echa un vistazo a W3 Schools. Este tutorial dura unas 10 horas.

Por supuesto, eres libre de encontrar tus propios tutoriales, o aprender haciendo.

Los fundamentos de las extensiones de Chrome

¿Qué son las extensiones de Chrome?

Las extensiones son pequeños programas de software que pueden modificar y mejorar la funcionalidad del navegador Chrome. Se escriben utilizando tecnologías web como HTML, JavaScript y CSS.

Si quieres saber más sobre las extensiones de Chrome, lee la introducción de Google a las extensiones y la descripción general de alto nivel de Google.

Punto de control 1: Cal to Butt

Con todo esto fuera del camino, vamos a empezar!

Tarea A: Leer el código de inicio

Antes de empezar a escribir cualquier código, lea el código de inicio y los comentarios que hemos proporcionado. En particular, lee todo src/inject/inject.js, porque harás la mayoría de tus cambios en ese archivo. Si tienes alguna duda, ¡ésta sería una gran oportunidad para pedir ayuda en nuestro canal de Slack!

Tarea B: Actualizar modifyText para reemplazar cada instancia de ‘cal’ con ‘butt’

Para la primera tarea, actualizarás la función modifyText en src/inject/inject.js para reemplazar cada instancia de la subcadena ‘cal’ con la cadena ‘butt’ en una palabra dada y devuelve la cadena modificada. Para la parte 1, la variable settings será null.

Por ejemplo, modifyText('calhacks organizer', null) debería devolver butthacks organizer.

/* File src/inject/inject.js */function modifyText(text, settings) {// YOUR CODE HEREreturn text;}

Prueba tu método visitando la página Wiki de UC Berkeley o el sitio web CalHacks. Personalmente, me gusta la página Wiki de Cálculo.

(Sugerencia: Revisa la documentación sobre el reemplazo de cadenas en JavaScript)

Casos de borde: ¿Qué pasa con la cadena 'iCalendar'? Intenta actualizar modifyText para que respete el caso original de la subcadena cal. Es decir, 'cal' -> 'butt', pero también 'Cal' -> 'Butt' y 'CAL' -> 'BUTT'. ¿Qué otros esquemas de mayúsculas y minúsculas comunes tendrá en cuenta su función?

Punto de control 2: Traducciones personalizadas

No somos los primeros en pensar en esto. Si usted lee XKCD, algo de esto puede parecerle familiar. Si no has leído XKCD, bueno, es el momento de tomar un descanso de codificación y leer algunos buenos webcomics a la antigua. Aquí están algunos de nuestros favoritos.

Batman

s/keyboard/leopard

XKCD Substitutions

Horse

Substitutions 2

Estos cómics muestran algunos grandes reemplazos de texto, que se reproducen aquí en formato de texto plano.

batman -> a man dressed like a batkeyboard -> leopardwitnesses -> these dudes i knowallegedly -> kinda probablynew study -> tumblr postrebuild -> avengespace -> spaaacegoogle glass -> virtual boysmartphone -> pokedexelectric -> atomicsenator -> elf-lordcar -> catelection -> eating contestcongressional leaders -> river spiritshomeland security -> homestar runnercould not be reached for comment -> is guilty and everyone knows itforce -> horsedebate -> dance-offself driving -> uncontrollably swervingpoll -> psychic readingcandidate -> airbenderdrone -> dogvows to -> probably won'tat large -> very largesuccessfully -> suddenlyexpands -> physically expandsfirst-degree -> friggin' awfulsecond-degree -> friggin' awfulthird-degree -> friggin' awfulan unknown number -> like hundredsfront runner -> blade runnerglobal -> sphericalyears -> minutesminutes -> yearsno indication -> lots of signsurgedrestraint by -> drunkenly egged onhorsepower -> tons of horsemeat

Y, por supuesto, nuestra propia

cal -> butt

Vamos a utilizar esta «sintaxis de flecha» para representar una regla de sustitución de texto para el resto de este proyecto. En particular, dejaremos que

pattern -> replacement

represente la transformación de la cadena "pattern" a la cadena "replacement". Por ejemplo, "years -> minutes" significa que sustituimos cada instancia de la subcadena "years" por la cadena "minutes", y "minutes -> years" significa que sustituimos cada instancia de la subcadena "minutes" por la cadena "years".

Tarea C: Parsear una lista de cadenas en un mapa de reglas de reemplazo.

Para esta tarea, escribirá la función parseSettings en src/inject/inject.js para convertir un array de entrada de líneas que representan reglas de reemplazo y dar salida a un mapa de patrones a sus reemplazos.

La firma de la función es

function parseSettings(lines) { // YOUR CODE HEREreturn null;}

Por ejemplo,

parseSettings()

debe devolver

{ "batman": "a man dressed like a bat", "keyboard": "leopard", "force": "horse"}

Se garantiza que cada entrada del array de líneas contiene la subcadena '->' al menos una vez.

Casos de borde: ¿Cómo procesa su función la línea "a -> b -> c". ¿La convierte en "a": "b -> c", en "a -> b": "c", o en otra cosa? ¿Qué pasa si no hay un patrón (es decir, la línea parece "->word" sin texto antes de la flecha)? ¿Y si no hay sustitución (es decir, la línea se parece a "word->" sin texto después de la flecha)? ¿Qué pasa con la línea con sólo 2 caracteres -> (es decir, sin texto antes o después de la flecha)? ¿Cómo maneja su función los espacios en blanco? ¿Procesa la línea " a -> b " como "a":"b" o como " a ": " b "? ¿Qué sucede si hay dos líneas diferentes, cada una con el mismo patrón? Por ejemplo, tal vez una línea de la matriz es "force->horse" y otra entrada es "force->fore"?

Tarea D: Usar un mapa de reglas de reemplazo para realizar varios reemplazos de texto

¡Habiendo completado la función parseSettings, ahora necesitamos volver a la función modifyText para usar nuestras nuevas reglas de reemplazo! El código de inicio tomará el valor de retorno de su función parseSettings y lo pasará a la función modifyText como la variable settings.

Para esta tarea, tendrá que actualizar modifyText en src/inject/inject.js, para que todas las reglas de reemplazo del mapa se promulguen.

Por ejemplo, si el mapa contiene una asociación entre "force" y "horse" (es decir, settings = "horse"), entonces cualquier instancia de la subcadena "force" debe ser reemplazada por la cadena "horse" en el texto, y así sucesivamente para el resto de los pares pattern: replacement en el mapa. Como siempre, debería seguir sustituyendo "cal" por "butt"

Casos de borde: ¿En qué orden se evalúan los reemplazos? Supongamos que settings = {'train':'bus', 'use':'eat'}. ¿Qué ocurre con la cadena "trainer"? ¿Se aplica primero train, lo que lleva a buser y luego a beatr? ¿O se aplica primero use (sin efecto), seguido de train para una cadena final de buser? Al igual que en el punto de control 1, ¿cómo se maneja el caso del texto original? ¿Existe una forma general de respetar el caso original?

Usando la acción del navegador.

Para probar esta función, le hemos proporcionado una acción del navegador para la extensión. En la esquina superior derecha de la ventana de Chrome, habrá un pequeño icono de TreeHacks).

Browser Action Icon

Haga clic en el icono para revelar una interfaz de usuario donde puede introducir reglas de reemplazo. Las reglas de sustitución que introduzca se pasarán a sus funciones y se aplicarán a la página. A continuación se muestra una captura de pantalla:

Browser Action

El texto que introduzca en este cuadro es persistente – no desaparecerá cuando cierre la ventana emergente. Si te interesa, el código para hacer esto está en src/browser_action/. Al pulsar el botón de guardar se guarda el texto en el almacenamiento local de Chrome, y al pulsar el botón de borrar se borra el almacenamiento local.

Punto de control 3: Reemplazo de imágenes

Para el tercer y último punto de control, ampliarás la funcionalidad de la extensión para permitir al usuario especificar los reemplazos de imágenes, al igual que los reemplazos de texto.

Dado que esta es la parte final del hackpack, te estamos dando un poco menos de orientación y un poco más de libertad aquí. Puede utilizar cualquier esquema de codificación que desee para representar las reglas de traducción de imágenes. Le sugerimos que utilice el esquema img->https://path.to/image.png para indicar que todas las imágenes deben ser reemplazadas por la imagen en https://path.to/image.png. Dependiendo de cómo elija representar sus reglas de reemplazo de imágenes, puede tener pasos distintos a los que se indican a continuación.

Tarea E: Encontrar todas las imágenes de una página web determinada.

Si queremos reemplazar todas las imágenes de una página web, primero necesitaremos tener todas las imágenes de esa página web. Escribe un método (de ayuda) que devuelva una lista de todas las imágenes de una página.

Puede que te sientas tentado a usar jQuery, pero ten en cuenta que incorporar jQuery en una extensión de Chrome no es fácil, y hay una forma de resolverlo usando vanilla JS. Si necesitas una pista, echa un vistazo a la documentación de querySelectorAll.

Tarea F: Actualizar parseSettings para manejar las reglas de reemplazo de imágenes además de las reglas de reemplazo de texto.

Tendrás que cambiar la implementación de parseSettings para buscar regla(s) de reemplazo de imágenes. ¿Cómo representará una regla de reemplazo de imágenes?

Tarea G: Actualizar la fuente de cada imagen en la página.

Una vez que tenga las imágenes y la URL de reemplazo, escriba código para actualizar la imagen original para que muestre la URL de destino. Si necesitas una pista, mira el atributo src de las imágenes.

Tarea H: Estamos todos juntos en esto

Con estos métodos de ayuda en la mano, implementa la función replaceAllImages en src/inject/inject.js. Esta función se llama inmediatamente después de evaluar los reemplazos de texto. ¡Si todo va bien, deberías ser capaz de introducir una regla de reemplazo de imágenes en la acción del navegador, y ver que todas las imágenes son reemplazadas!

¡Felicidades!

¡Lo has conseguido! Muy bien hecho. Has construido una extensión de Chrome que reemplaza el contenido en los sitios web, y lo que es más, ¡puedes mantenerlo!

Tómate un momento para relajarte, respirar profundamente, y mirar hacia atrás en el proyecto que has construido. Es muy impresionante!

Si llegas a este punto, ven al canal de Slack #hackpack-chrome-ext para celebrarlo! Te lo mereces.

Extensiones

A un alto nivel, has construido un sistema que se basa en el paso de mensajes entre un diálogo emergente (acción del navegador Chrome) y un script que se ejecuta en cada página web. Hemos estado usando esto para pasar información sobre los reemplazos de texto e imágenes al script de inyección, pero no hay razón para que tengamos que parar ahí.

Puedes extender este framework para construir proyectos realmente interesantes. El cielo es el límite, pero hemos dado algunas sugerencias aquí.

  • Compare más que sólo texto plano – ¡compare expresiones regulares! Extienda la funcionalidad de modifyText para tratar los patrones de settings como representación de expresiones regulares, no sólo de texto plano.
  • Apoye la coincidencia en selectores de documentos del DOM. Coincidir con nombres de etiquetas (como img, pero también a y iframe), o nombres .class, o incluso #ids. ¿Puedes crear soporte para el conjunto completo de selectores?
  • No reemplaces todas las imágenes – sólo reemplaza algunas (digamos el 1%). ¿Podría cambiar los enlaces de youtube (etiquetas a con un href que contenga "youtube") por vídeos de Rick Astley?

Alejándose del ámbito de los reemplazos,

  • Permita al usuario señalar información al script de fondo. Quizás preguntarle su nombre, y resaltar en rojo cualquier texto que contenga su nombre.
  • Dejar que el usuario especifique un montón de servidores para que actúen como proxies. Has construido un Tor básico.
  • Permite que un usuario introduzca sus datos de salud, y sugiere (a través de un popup amigable o una redirección) que se ejercite cada periodo de tiempo que pase navegando por un sitio (cough reddit cough).

Esto es sólo el principio. Deja volar tu imaginación. No podemos esperar a ver lo que construyes!

Varios

Comentarios

Si tienes algún comentario, positivo o negativo, ponte en contacto con Sam Redmond (@organizer-sam en Slack) con comentarios! Nos encantaría escuchar lo que piensas que es genial, y lo que crees que podemos mejorar.

Crédito

El crédito por la idea es para los creadores de la extensión de Chrome Cloud-to-Butt, el crédito por la gran documentación (gran parte de la cual robamos descaradamente) es para los colaboradores de Chromium, y el crédito por las imágenes es para XKCD.

Licencia

MIT