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

Mantén la consistencia de tu código con .editorconfig

Generalmente tenemos un editor de cabecera, ese aliado que nos acompaña en todas nuestras aventuras de código, pero en ocasiones nos vemos obligados a usar un editor distinto a nuestro leal amigo (o lo que es peor un IDE), por lo que la consistencia de nuestro código podría llevar los platos rotos.

Pero sabemos que en el mundo del desarrollo y la tecnología casi siempre hay una propuesta para este tipo de entresijos, EditorConfig:

EditorConfig ayuda a los desarrolladores a definir y mantener guías de estilo para código consistente entre editores e IDEs.

El proyecto EditorConfig consiste en un formato de archivo que sirve para definir estilos de código y una colección de plugins para editores de texto que permiten a los editores leer el formato de archivo y adherir los diferentes estilos.

Los archivos de EditorConfig son fáciles de leer y trabajan muy bien con sistemas de control de versiones.

En nuestro proyecto agregaremos un archivo llamado .editorconfig dónde volcaremos todas esas reglas de estilo de código (tamaño de sangría, soft tabs o hard tabs entre otros), ¡podemos definir reglas para distintos formatos de archivos!.

Brackets, Atom.io y Sublime Text son 3 de los muchos editores compatibles con .editorconfig
Brackets, Atom.io y Sublime Text son 3 de los muchos editores compatibles con .editorconfig

No detallaremos como instalar los plugins de .editorconfig para cada uno de los editores que soportan, en la web oficial lo hacen muy bien, nos concentraremos en la sintaxis, la cual se divide en:

  • Los patrones de comodines: estos se expandirán según sea el caso para coincidir con el patrón que queramos, los cuales no son más que las expresiones regulares de toda la vida.

  • Las propiedades: que aplicaran las reglas para mantener la consistencia del código.

Comodines

  • *: Coincide con cualquier cadena de caracteres, excepto con el separador de ruta (/), ejemplo una regla con [*] se aplicará a todos los archivos en el proyecto o [*.css] a todos los archivos css.

  • **: Coincide con cualquier cadena de caracteres.

  • ?: Coincide con un sólo carácter.

  • [nombre]: Coincide con cualquier carácter individual en “nombre”, por ejemplo [app.js].

  • [!nombre]: Coincide con cualquier carácter individual que NO esta en nombre.

  • {s1,s2,s3}: Coincide con cualquiera de las cadenas dadas (separadas por comas).

Propiedades

  • root: Propiedad especial que debe especificarse al inicio del archivo, con valor true, esto le dirá a los plugins de cada editor que debe aplicar las reglas de estilos de código incluidas en ese archivo.

  • indent_style: establece el tipo de indentación a “tab” o “espaciado”, hard-tabs y soft tabs respectivamente.

  • indent_size: especifica el tamaño de la indentación según el tipo de que se haya elegido con la propiedad indent_style (o con el estilo indentación por defecto en el editor si no se especificó ninguna).

  • end_of_line: establece el tipo de final de línea, sus posibles valores son “lf”, “cr”, or “crlf”.

  • chartset: específica la codificación de carácteres, los posible valores son “latin1″, “utf-8″, “utf-8-bom”, “utf-16be” o “utf-16le” siendo “utf-8-bom” desaconsejado.

  • trim_trailing_whitespace: si esta propiedad tiene como valor true se removerá cualquier espacio antes de cada nueva línea, false hará lo contrario.

  • insert_final_newline: establecer true agregará una nueva línea al final de todos los archivos.

Ejemplo .editorconfig

# Comentarios con la almohadilla

# root siempre debe ir al inicio del archivo .editorconfig
root = true

# Aplicar esta regla a todos los archivos en el proyecto, usa expresiones regulares, aplica final de linea estilo Unix e inserta una linea al final de cada archivo
[*]
end_of_line = lf
insert_final_newline = true

# Aplica a varios tipos de archivo (javascript y python) una codificación de caracteres utf-8 gracias a las llaves ()}).
[*.{js,py}]
charset = utf-8

# 4 espacios de indentación para archivos de python
[*.py]
indent_style = space
indent_size = 4

# Indentación por tabs (tamaño de las tabs no especificado) para todos los archivos javascript del proyecto
[*.js]
indent_style = tab

# La indentación se sobreescribe para todos los archivos javascript dentro la capeta libs
[lib/**.js]
indent_style = space
indent_size = 2

# Aplica reglas a archivos específicos colocando el nombre de archivo completo junto con su ruta en el proyecto.
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2

Conclusión

Sin duda .editorconfig es intuitivo y útil, una vez domines su uso podrás, por ejemplo, armar una colección de archivos según el proyecto en el que hayas trabajado, por lo que también es reutilizable.

Sólo debes andarte con ojo, los plugins para cada editor no suelen soportar todas las propiedades de .editorconfig, por lo que antes de usarlo dale una repasada al soporte que ofrecen, de resto sólo queda decir: por favor, mantén la consistencia de tu código con .editorconfig.

¿Usabas .editorconfig?, comparte tu configuración preferida en los comentarios y cuentanos por qué la usas.

Enlaces de interés

API HTML5: Visibilidad de Página

HTML5 es modular, por lo que cada uno de sus componentes se desarrolla a una velocidad distinta dependiendo (entre otras cosas) de su complejidad, propuestas varias, sin además olvidar la implementación progresiva de cada uno de estos componentes en los navegadores modernos, entre un montón de nuevas características se encuentra el API HTML5 visibilidad de página (Page Visibility API) la cual en palabras llanas nos permite saber que pestaña del navegador se encuentra activa y a partir ejecutar las acciones que cambien el comportamiento de nuestra web o aplicación web.

Veamos un ejemplo sencillo, una vez ingreses en el enlace anterior selecciona o abre cualquier otra pestaña de tu navegador y luego vuelve a enfocar la pestaña del ejemplo para modificar el comportamiento de la página.

Funcionamiento

Simple, el objeto document cuenta con una propiedad llamada hidden que no es más que un boleano que será true cuando la pestaña actual no este seleccionada o enfocada (es decir, el contenido de la pestaña no es visible para el usuario) en caso contrario valdrá false.

El cambio de esta propiedad puede ser manejado con el evento visibilitychange proporcionado por la API, este evento se dispara cuando el contenido cambia del estado visible a oculto y viceversa: cuando enfocamos o desenfocamos una pestaña.

La propiedad document.hidden cubre la mayor parte de los casos de uso pero además esta API viene con una propiedad adicional: document.visibilityState que sólo está disponible dentro del manejador de eventos para visibilitychange, esta propiedad retorna una cadena la cual nos dice por qué la pestaña actual está oculta lo cual nos da una mayor exactitud, los posibles valores y su significado son los siguientes:

  • visible: El contenido de la página debe estar parcialmente visible, es decir la pestaña que tenemos actualmente abierta y enfocada en el navegador en una ventana no minimizada.

  • hidden: El contenido de la página no es visible al usuario, ejemplo: una tab que abre en segundo plano en móviles o el screenlock se encuentra activo, en escritorio es la pestaña seleccionada en una ventana minimizada.

  • prerrender: El contenido de la página está siendo pre-renderizado y no es visible para el usuario (document.hidden considera este estado como true).

  • unloaded: La página es descargada de la memoria, es decir, la pestaña ha sido cerrada.

Con esto en mente, examinemos a fondo el código del ejemplo anterior:

<div class="container">

  <div class="row">

    <h2 class="text-center">
      Ejemplo API de Visibilidad de Página HTML5
    </h2>

    <div class="small-12 text-center" id="aviso">
      Hola has enfocado la pestaña <span id="contador">0</span> veces

      <p>
        <strong>
          Texto visible sólo un segundo después de que la pestaña esté seleccionada/enfocada.
        </strong>
      </p>

      <h3>
        Historial
      </h3>
      <textarea id="historial" cols="30" rows="10">
      </textarea>
    </div>

  </div>

  <small>
    <a href="http://lordcaos.com.ve/2015/02/api-html5-visibilidad-de-pagina">
      Vuelve al artículo.
    </a>
  </small>

</div><!-- ./Marcado base para el ejemplo -->
/* 
visibilityChange guardará una cadena con el nombre del evento de la API de visibilidad según el navegador que este usando el usuario 
*/
var visibilityChange = null,
    contador = 0,
    spanContador = document.getElementById("contador"),
    historial = document.getElementById("historial"),
    textoOculto = document.getElementsByTagName("p");

/* 
Preparando el crossbrowser, esta técnica de detección necesaria para utilizar que prefijo de navegador y así obtener el nombre del evento adecuado (visibilitychange, mozvisibilitychange, msvisibilitychange o webkitvisibilitychange) o el ejemplo no funcionará 
*/
if( typeof document.hidden !== "undefined" ) {
  oculto = "hidden";
  visibilityChange = "visibilitychange";

} else if( typeof document.mozHidden !== "hidden" ) {
  oculto = "mozHidden";
  visibilityChange = "mozvisibilitychange";

} else if( typeof document.msHidden !== "undefined" ) {
  oculto = "msHidden";
  visibilityChange = "msvisibilitychange"

} else if( typeof document.webkitHidden !== "undefined" ) {
  oculto = "webkitHidden";
  visibilityChange = "webkitvisibilitychange"
}

function manejadorCambioVisibilidad() {

  /* 
  Esta es la parte que nos interesa, si la pestaña está oculta (es decir document.hidden es verdadero) entonces actualizamos el innerHTML del spanContador, dejamos un mensaje en el historial o tomamos la acción que vayamos a tomar cuando la pestaña este oculta
  */
  if( !!document[oculto] ) {
    spanContador.innerHTML = contador;

    textoOculto[0].style.visibility = "hidden";
    historial.innerHTML += "La página estuvo oculta n";

  } else {
    contador += 1;
    historial.innerHTML += "La página está visible n";

    setTimeout(function() {
      textoOculto[0].style.visibility = "visible";
    }, 1000);


  }

}

/* 
Asignamos el manejador de eventos al objeto document de la página y listo 
*/
document.addEventListener( visibilityChange, manejadorCambioVisibilidad, false);

Soporte

Recordemos que esta característica tiene estatus de W3C Recommendation por lo que debería estar lista para usarse en la mayoría de los navegadores modernos, cosa que nos confirma caniuse la cual le da 84% de soporte global y 74% sin prefijos de navegador, sólo con navegadores como Interner Explorer <=9 u Opera Mini 8 como excepción.

En resumen, si en tu proyecto no debes darle soporte a alguno de esos navegadores entonces usa la API de visibilidad con toda confianza (sin olvidar la técnica de detección de más arriba para los prefijos de navegador o usar modernizr).

Conclusión

Como mencioné, es un ejemplo muy sencillo, en la práctica está API puede ser de utilidad para ahorrar recursos, por ejemplo pausar un slider mientras el usuario no está viendo la web, detener una petición al servidor, pausar un vídeo o una canción, o simplemente llamar la atención del usuario en el momento preciso que vuelve a enfocar la página.

La API de visibilidad de página no es tan compleja o impresionante como Canvas, Webgl o SVG pero cumple su cometido y pienso que se hará un espacio en aquellas situaciones donde se utilizaba onblur/onfocus sobre la ventanta para recrear la funcionalidad de visibility page.

Fuente:
Smashingmagazine

Especificación Oficial, documentación y ejemplos:
W3C Page Visibility
MDN
Primer Ejemplo
Ejemplo con audio