Resaltador MarkIt
Este es un enlace de extensión de Chrome que le permite resaltar texto importante en cualquier página web. Vuelva a visitar la página en 1 minuto, 1 semana o 1 año; sus datos siempre estarán allí.
Tecnologías
- (Vainilla) JavaScript
- API de Google
Características
- Resalte cualquier texto y presione Comando+K para guardarlo automáticamente
- El usuario puede borrar los aspectos destacados almacenados para cualquier URL con un simple comando, Comando+Mayús+A
- Se sincroniza en todos los dispositivos: si resalta texto desde una computadora portátil y luego mira la misma página web desde su teléfono, sus aspectos destacados estarán allí (si ha iniciado sesión en Chrome en ambos).
Mi estructura de datos almacenados (objeto)
highlights = {
google.com: {
text1: ["query selector", index, note, color]
text2: ["query selector", index, note, color]
},
yahoo.com: {
text3: ["query selector", index, note, color],
text4: ["query selector", index, note, color]
},
https://developer.mozilla.org/en-US/docs/Web/API/document/execCommand: {
"When an HTML document has been switched to designMode, its document object exposes an execCommand": ["p.summary", 20],
"A DOMString specifying the name of the command to execute. See Commands for a list of possible commands.": ["p", 0, "example note", #CFFFDF]
}
}
Cómo funciona
Tengo dos scripts que se cargan en cada página. El primero es background.js que escucha un evento específico. El evento Comando+K activa una función que inyecta un script en el navegador (injection_script.js), que resalta el texto seleccionado.
Para resaltar, arrastre el mouse sobre un texto y presione Comando + K. Esto desencadena una función que llama a varias otras. Secuencia de eventos:
- Toma el texto seleccionado
- Activa el modo de diseño, lo que nos permite realizar cambios temporales en el DOM.
- Si el fondo ya está resaltado, entonces debemos eliminarlo:
- Selecciona la etiqueta < span > que rodea el texto y establece style.backgroundColor = transparent (elimina el resaltado)
- Obtiene el objeto 'destacados' del almacenamiento:
chrome.storage.get()
- Recorre todas las claves (que son los aspectos destacados guardados) para buscar una coincidencia y la elimina del almacenamiento.
- De lo contrario, ajuste el texto en un < span > y aplique el color de fondo
- Actualización de la página: recuperar 'destacados' del almacenamiento
- Si no hay datos para la URL activa, establezca la clave en la URL actual y el valor en un objeto vacío (aol.com: {})
- Si es así, tome la estructura de datos destacada del almacenamiento (chrome.storage.get())
- Recupere y asigne un valor de selector de consulta válido para el texto seleccionado (esto se usará para consultar el DOM y aplicar los aspectos destacados más adelante. Consulte la estructura del objeto anterior para obtener una aclaración).
- Si el elemento principal del texto resaltado tiene un nombre de clase, almacene una cadena "element.className" ("p.firstParagraph", "h2.sectionHeader", etc.)
- Si no hay un nombre de clase, almacene la cadena "elemento" ("p", "h2", "li", etc.)
- Asigne un valor a la clave (texto resaltado) (una matriz que contiene 2 valores: primero, el selector de consulta y segundo, el índice de donde apareció el texto seleccionado en el elemento principal)
- Almaceno el índice de la cadena porque si solo almacené el texto y el selector de consultas, digamos que resaltó "el" bajo una etiqueta "p", al aplicar los resaltados si actualiza la página, cada aparición de "el" en un La etiqueta "p" quedará resaltada. Agregar el valor indexOf me permite verificar que los índices coincidan con el DOM y solo entonces aplicar el resaltado, por lo que aplico el resaltado a la palabra correcta.
- Almacene la variable resaltada actualizada que contiene el nuevo texto resaltado usando chrome.storage.set()
- Desactivar el modo de diseño
El segundo archivo JavaScript que se ejecuta en cada página es content_script.js. Comprueba si hay un objeto almacenado llamado "destacados". Si no lo hay, significa que el usuario nunca ha resaltado nada. Luego creó un objeto vacío y lo almacena en Chrome.
Si encuentra un objeto 'destacado', comprueba si hay datos almacenados para la URL activa. Si no es así, el script regresa.
Si hay aspectos destacados almacenados para la URL:
- Se ejecuta la función applyHighlights()
- Se necesitan dos parámetros, el objeto 'destacados' y la URL activa.
- Recorre las claves del objeto almacenado (las claves son los aspectos destacados almacenados, mientras que los valores de esas claves son una matriz que contiene los valores querySelector e indexOf)
- Ejecuta document.body.querySelectorAll() para obtener una matriz de todos los nodos coincidentes.
- Recorre cada nodo devuelto y si el HTML interno contiene una "cadena" que coincide con la clave del objeto (texto resaltado) Y en el mismo valor indexOf: 1. Ejecuta una función .replace() que envuelve el texto coincidente en una etiqueta < span > con un atributo de estilo en línea para el color de fondo
- Nota al margen: originalmente revisé cada nodo DOM de forma recursiva para verificar si había coincidencias, pero almacenar el valor de querySelector y comparar los valores HTML de solo los nodos coincidentes con mis valores almacenados es significativamente más rápido.
Actualizaciones para la próxima versión
- Almacene la cadena específica que destacó
- "Descargue la biblioteca jQuery desde jQuery.com".
- Si resalta el segundo "jQuery", el valor almacenado será de primera instancia.
- Esto se debe a que el valor indexOf que almaceno regresa después de la primera coincidencia.
- PLAN: comience a contar el índice después de la etiqueta de intervalo
- no se puede resaltar entre elementos del bloque (si arrastra el resaltado desde un h2 a la etiqueta ap, solo se registrará el h2)
- EN CURSO: permitir a los usuarios elegir el color de resaltado
- Haga que la cantidad de aspectos destacados y aspectos destacados reales de una página aparezcan en la extensión popup.html
- Limitaciones/casos extremos: correo electrónico, archivos PDF
- Solicito permisos para cada sitio. al cual algunos sitios bloquean el acceso '*' (cnn.com)
- Si resalta "jQuery" en un elemento, y lo resalta nuevamente en otro, el segundo anula el primero (porque la clave es la misma)
- Si el elemento principal es una etiqueta en línea, el indexOf de texto interno/html no se registra (-1) o finaliza el resaltado al final de la etiqueta en línea. Encuentre el índice de la etiqueta span e inicie el indexOf allí.
- Modo contraer: contrae el documento solo a los elementos principales de los aspectos destacados almacenados
Problemas resueltos
- Almacenamiento de aspectos destacados que abarcan etiquetas de elementos en línea (a, em, st, etc.)
- Antes, solo se guardaba el texto antes de la etiqueta en línea, porque almacenaba el texto interno
- Lo resolví almacenando el HTML interno en su lugar.
- El problema que surgió de este cambio fue que estaba almacenando el índice del texto interno, que volvería a aplicar los resaltados al texto estándar dentro de un elemento de texto, como una etiqueta "p". Pero indexOf es diferente para elementos alrededor de elementos en línea porque indexOf cuenta cada carácter en las etiquetas.
- Para resolver esto, comparo los valores de InnerText.indexOf Y InnerHTML.indexOf y comparo cada uno con nodos coincidentes cuando aplico resaltados a las páginas que un usuario está visitando nuevamente.
- Si hacía doble clic para resaltar una sección, los valores indexOf no se registraban y, por lo tanto, mi aplicación no podía volver a aplicar los resaltados.
- Para resolverlo agregué los métodos .toString() y .trim() al indexOf(...)
- Resaltar una etiqueta < a > eliminaría el enlace al cargar la página.
Actualizaciones futuras
## Imagen de ejemplo
Casos extremos
- Si los nombres de las clases cambian
- Solución: si el nombre de la clase no existe en el DOM, elimine el nombre de la clase del selector de consultas y simplemente busque los nodos de etiqueta del elemento
- Si el contenido está oculto mediante un botón, mis aspectos destacados no se registrarán porque busca on_load y el contenido solo se revela después de un evento del navegador (es por eso que no funciona en el correo electrónico)
Permitir que alguien acceda a todos los aspectos destacados en popup.html. Permitir a los usuarios cambiar el color del resaltador. Reparar el error de resaltado del elemento en línea.