Hacer figuras de commits en la actividad pública de github

¡Advertencia no leer!: El siguiente articulo es un productivity killer, es decir, una pérdida de tiempo que no te dejará nada productivo… pero seguro te saca una sonrisa.

Github Contributions – Imagen tomada del repositorio oficial https://github.com/IonicaBizau/github-contributions/
Github Contributions – Imagen tomada del repositorio oficial https://github.com/IonicaBizau/github-contributions/

Esta es una nota curiosa, seguramente en alguno de tus perfiles sociales te gusta agregar algún emoticons/sticker/emoji que te permita expresar mejor tus emociones sumado a imágenes de fondo, colores, o lo que el servicio te permita, este tipo de personalización no es ajena del mundo del desarrollo donde existen desde lo mas a variados a los mas geeks.

Github Contributions es el proyecto que se encarga de generar un llamativo calendario de contribuciones en tu perfil de github, su instalación vía NPM:

$ npm install -g gh-contributions

Se lanza con:

$ gh-contributions

El comando anterior iniciará un servidor web local en 127.0.0.1:9000 al que accederemos desde nuestro navegador y terminará mostrando el generador (primera imagen del post), luego todo es increíblemente sencillo:

Generador de figuras en el gráfico de contribuciones de github
Generador de figuras en el gráfico de contribuciones de github
  1. Crea la figura que quieres que aparezca en tu cuenta github.

  2. Seleccionar “Generate repository from data”, una vez terminado ese proceso “Click here to download the repostory”.

  3. Crear un nuevo repositorio en github, por ejemplo, al mio lo llamé grafico-contribuciones-hack.

  4. Agregar el repositorio remoto que acabamos de crear en el paso 3 al repositorio local que creamos en el paso 2.

  5. Hacer git push --all.

Gráfico en todo su esplendor en mi perfil de github
Gráfico todo su esplendor en mi perfil de github

Si llegaste hasta aquí y seguiste las instrucciones (cosa no difícil con un conocimiento básico de git y github): ¡te felicito!, has perdido tu tiempo pero vamos ¡puedes hacer figuritas en tu perfil de github!, facebook temblad.

postMessage: Comunicación bidireccional cross-origin con un iframe

Cuando necesitábamos pasar algún tipo de dato desde un sitio padre a un iframe same-origin una de las opciones con la cual contábamos era agregar el dato que quisiéramos pasar a la propiedad contentWindow de dicho iframe, pero, ¿qué hay con el cross-origin?, ¿es ademas el primer método cien por cien confiable para same-origin?, afortunadamente HTML5 trajo consigo un API para mensajería web mismo o distinto origen 13 Sin necesidad de técnicas CORS como JSOP por ejemplo.: postMessage.

Ejemplo sencillo

Llamemos al iframe que recibirá los datos remoto (estará alojado en el blog) y el sitio web padre será el origen (estará alojado en jsfiddle), el origen iniciará la comunicación, por ejemplo enviando el value de un input o textarea:

Todo mensaje enviado desde el dominio http://fiddle.jshell.net será recibido por el iframe remoto (caja inferior del ejemplo), el código del sitio remoto puedes verlo en detalle en github.

postMessage en detalle

Página remota

La pagina remota de nuestro ejemplo, registra un evento message que virtualmente estará a la escucha de todas las peticiones postMessage que se realicen al iframe, el objeto evento tiene tres propiedades de nuestro interés:

  • e.data: el objeto enviado por el origen, en nuestro ejemplo anterior el valor del atributo value en el textarea del origen.

  • e.origin: el origen de la ventana que envió el mensaje al momento en que el método postMessage fue invocado, es el resultado de la concatenación de tres elementos: protocolo (“://”), el hostname si existe y, en caso de ser distinto al por defecto, el número de puerto (“:”), en nuestro ejemplo el origin es http://fiddle.jshell.net.

  • e.source: Es una referencia directa a la ventana origen que envía el mensaje, es excelente para establecer la comunicacion bidireccional que buscamos pero hay que usarla con cuidado sólo con origenes/dominios confiables.

Cada llamada al método window.postMessage disparará un evento messageEvent que traerá consigo el tipo de mensaje (e.data) y el origen de la petición (e.origin).

window.addEventListener("message", function(e) {

Es de suma importancia filtrar el origen de cada petición, si no estaremos ante un problema de seguridad, por ejemplo, un sitio malicioso podría enviar/recibir datos al evento messageEvent de la pagina remota/origen sin que nada se lo impidiese.

var origen = e.origin,
    datos = e.data;

// Solo acepta peticiones de http://fiddle.jshell.net, al resto mandalos a freir
// esparragos
if(origen === "http://fiddle.jshell.net") {

Finalmente, si la petición pasa la verificación utiliza e.source para notificarle al origen que todo ha ido bien y actualizando el texto del iframe con la información recibida.

textoEnRemoto.innerHTML = "El mensaje enviado por el origen  "+ origen +" fue: "+datos;

e.source.postMessage("exito!", e.origin);

Página de origen

Antes de analizar el código de la pagina de origen echemos un vistazo al método window.postMessage, este puede ser llamado sobre una ventana de navegador valida (iframe, window.open, entre otros) 14En realidad postMessage también es utilizado por Web Workers para intercambiar datos pero eso es material para otro articulo, más información :

ventanaValida.postMessage(mensaje, urlDeRemoto, transferible);
  • mensaje/message: El objeto que se va a enviar al iframe remoto, acepta distintos tipo de argumentos gracias al algoritmo de clonación estructurado, por el momento usaremo solo cadenas y mas adelante hablaremos sobre como pasar arrays y objetos.

  • origenRemoto/targetOrigin (opcional): Este argumento restringe a cual URL esta permitida realizar la llamada ventanaValida.postMessage,el valor * elimina la restricción pero siempre es recomendable indicar la URL de la ventanaRemota, para restringir las comunicaciones a unicamente same-origin debe ser pasado el valor /.

  • transferible/transfer (opcional): Es una secuencia de Transferable objects que son transferidos con el mensaje, la propiedad de esos elementos se transfiere a la página remota y dejan de estar disponibles en el origen.

Ahora el sitio de origen, primero registramos un evento message para estar a la escucha de cualquier mensaje de respuesta enviado por el iframe remoto.

window.addEventListener("message", function(e) {
  var confirmacion = document.getElementsByTagName("small")[0],
      origenRemoto = e.origin;

  // Solo acepta peticiones de http://lordcaos.com.ve,
  // el resto ignoralas
  if(origenRemoto ==  "http://lordcaos.com.ve") {
    confirmacion.innerHTML = "Confirmación el iframe con origen " + origenRemoto +
    " ha recibido el mensaje que le hemos enviado y lo ha notificado";
  }
}, false);

Luego, siguiendo el primer ejemplo, cada vez que se haga click en el botón de la ventana origen se envía una petición postMessage unicamente al origenRemoto/targetOrigin especificado (es decir, el sitio remoto).

iframe.contentWindow.postMessage(textarea.value, "http://lordcaos.com.ve/ejemplos/postMessageRemoto/remoto.html");

Enviado distintos tipos de objetos y el argumento transferible

Podemos enviar distintos tipo de objetos vía postMessage, no solo cadenas, estos objetos son serializados con el algoritmo de clonación estructurado (que se merece un articulo sólo para él), en el segundo ejemplo puedes verificarlo (así como el uso de e.source y el argumento Transferible).

El segundo ejemplo muestra dos cosas interesantes, primero, hemos pasado distintos tipos de elementos además de cadenas tales como arrays y objetos, que a su vez contienen otros objetos, valores boleanos e inclusive expresiones regulares, todos estos utilizables a través del algoritmo de clonación previamente nombrado.

  ...
  var datos = {
    str: "Cadena de texto",
    bool: true,
    num: 42,
    obj: {
      regExp: new RegExp(/.?/),
      date: new Date()
    },
    array: [1, "foo", "bar", true, false, { foo: "bar" }]
  },
  ...

  $remoto.get(0).contentWindow.postMessage(datos[seleccion], targetOrigin);

  ...

Segundo, pasamos el argumento transfer como un ArrayBuffer con longitud de byte igual a 5 (byteLength) para luego en el remoto crear una vista para ese buffer con un array tipado (TypedArray) gracias a new Int8Array(), lo importante aquí es que: una vez es enviado a nuestro remoto el ArrayBuffer no estará disponible nunca más en la página origen durante la sesión actual de navegación.

  ...
  transferable = new ArrayBuffer(5),
  ...

  $remoto.get(0).contentWindow.postMessage(transferable, targetOrigin, [transferable]);

  ...

Podemos comprobarlo en el ejemplo si seleccionas la primera vez mostrar transferable mostrará el texto Longitud de byte de este ArrayBuffer es 5, luego enviar transferible, al seleccionar por segunda vez mostrar transferable el texto será Longitud de byte de este ArrayBuffer es 0, siendo que el ArrayBuffer no está disponible en la página de origen.

Recuerda que el código completo de estos ejemplos puedes encontrarlo en su repositorio de github.

Soporte

Al momento de escribir este articulo, postMessage es soportado por una amplia gama de navegadores en su modo más básico, es decir sin el argumento transfer, el uso de este último solo lo soporta Firefox a partir de la versión 20 15Aunque el segundo ejemplo fue probado en Chrome 45.0.2454.85 (64-bit) y el argumento transfer funcionó sin problemas, para más información verifica la tabla de Compatibilidad de postMessage.

Un polyfill recomendando es iframeResizer, que si bien su funcionalidad principal es mantener la proporcionalidad del tamaño del iframe segun cambia el viewport, ofrece un API bastante conveniente para postMessage, compatible con navegadores modernos y no tan modernos (IE8);

Conclusión

Esta API sin duda facilita la comunicación con iframes, de forma nativa y segura si filtras los orígenes/remotos que envían y reciben mensajes, una regla de oro es si no esperas mensajes entonces no registres ningun evento messageEvent asi como también chequear que el tipo de dato recibido sea el deseado o esperado. Más allá de eso hemos visitado varios termino interesantes en este articulo, TypedArray y ArrayBuffer, Transferable Objects, algoritmo de clonación estructurado, entre otros, términos que espero estemos viendo en próximos posts.

¿Ya conocías postMessage?, ¿deberíamos usarla o evitarla por cuestiones de seguridad?, cuéntanos tu experiencia con esta API Web.

Zeal y Devdocs.io, la documentación offline definitiva

Además de míticos sitios de documentación para varias de las principales tecnologías web, como MDN, Web Platform Docs, generalmente suelo visitar devdocs.io que cumple la maravillosa tarea de organizar las más populares documentaciones de tecnologías y librerías, funciona parcialmente offline con los elementos que hayas seleccionado, tiene un catalogo impresionante y en constante crecimiento.

El código de devdocs.io se distribuye bajo licencia Mozilla Public License v2.0, puede usarse en móviles y cuenta con extensiones para Chrome y Firefox
El código de devdocs.io se distribuye bajo licencia Mozilla Public License v2.0, puede usarse en móviles y cuenta con extensiones para Chrome y Firefox

Pero a veces necesitaba completamente documentación offline, practicidad o sencillamente para cuando el internet falla y bueno conversando con @samuel me comenta sobre Zeal, decidí darle una oportunidad: ¡es impresionante!.

Zeal se define así mismo como un navegador de documentación fuera de linea (offline documentation browser), esta inspirado en Dash que solo esta disponible para Mac OS X, Zeal tiene versión para Windows y varias distribuciones Linux, así como su código es software libre bajo la licencia GPLv3.

Instalación

Todo depende de tu sistema, en Windows el instalador no tiene perdida y en Ubuntu/Mint vía ppa:

# add-apt-repository ppa:jerzy-kozera/zeal-ppa
# apt-get update
# apt-get install zeal libqt5sql5-sqlite

Funcionamiento

Una vez iniciado su funcionamiento es intuitivo, al estilo de devdocs.io, aunque a diferencia de este último Zeal no viene por defecto con ninguna documentación por lo que para descargarlas iremos a File -> Options:

En Options nos interesa la pestaña Docsets, allí zeal se encargará de descargar toda la documentación ofrecida en su catalogo, por ejemplo: Bootstrap, AngularJS, Laravel, el catalogo no es nada desdeñable.

A través de update docsets mantienes la documentación actualizada, también se pueden agregar fuentes de documentación adicionales aunque personalmente no he probado esa característica (Add Feed).
A través de update docsets mantienes la documentación actualizada, también se pueden agregar fuentes de documentación adicionales aunque personalmente no he probado esa característica (Add Feed).

Luego de aplicar y guardar los cambios explora o usa el buscador para ver la documentación descargada disponible en todo momento.

Los filtros te ayudan a encontrar fácilmente en una documentación especifica, es útil cuando se tienen muchos docsets descargados.
Los filtros te ayudan a encontrar fácilmente en una documentación especifica, es útil cuando se tienen muchos docsets descargados.

No descuidemos las opciones

Recomiendo revisar las demás opciones de Zeal, cuenta con algunas interesantes como asociar una combinación de teclas para invocarlo cómodamente, cambiar el directorio dónde se alojan los Docsets, así como características interesantes como los filtros para las búsquedas, por ejemplo javascript:join cercará tu búsqueda a dicho lenguaje.

Integración con Editores

Como muchos otros proyectos relacionados con el desarrollo se han creado plugins para editores populares, no vamos a detallar en este articulo como instalarlos porque cada uno de los sitios muestran como hacerlo pero si que dejaremos los enlaces:

Conclusión

Zeal es sin duda una tremenda aplicación, aumenta tu productividad considerablemente ya que pone al alcance de tu mano docenas de documentaciones de forma sencilla.

El proyecto está en sus primeras fases de desarrollo por lo que puedes esperar cambios drásticos en el funcionamiento de la aplicación entre versión y versión, así como algunos errores pueden aflorar de vez en cuando, frecuentemente memory leaks pero en conjunto con devdocs.io son herramientas potentes que te evitan tener diez pestañas de documentación abiertas o recurrir a google para buscar nombre de un método que no recuerdas.

Cuéntanos tu experiencia, ¿conoces alguna herramienta o sitio similar?.

Enlaces de interés