Grunt jshint

Categories:

JSHint es una herramienta que nos puede ayudar a mejorar la calidad del código que escribamos.

Esta herramienta detecta errores y problemas potenciales en el código de JavaScript además de que se pueden ajustar a las convenciones de codificación de tu equipo de trabajo.

JSHint se puede utilizar directamente con node.js pero lo vamos a utilizar con grunt.

Para utilizar jshint en nuestro proyecto – una vez que instalamos grunt – seguimos el proceso utilizado con otros módulos.

  1. Instalar el módulo
  2. Incluir el módulo, definimos la tarea en el archivo Gruntfile.js
  3. Ajustar las preferencias de la tarea – dentro de Gruntfile.js –

Instalar el módulo

$ npm install grunt-contrib-jshint --save-dev
Incluir jshint
Incluir jshint

Una vez instalado el archivo package.json debe incluir la dependencia del módulo – grunt-contrib-jshint -.

{
  "name": "demo",
  "version": "0.1.0",
  "private": "true",
  "description": "Crear un paquete json para utilizar grunt",
  "main": "index.html",
  "author": "eamexicano",
  "license": "MIT",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-jshint": "^0.10.0"
  }
}

Incluir el módulo

En el archivo Gruntfile.js necesitamos:

  1. Incluir el módulo que tiene la tarea – jshint -.
  2. Registrar la tarea.
  3. Configurar la tarea.

module.exports = function(grunt) {

  grunt.initConfig({ 
// 3.  Configurar la tarea
    jshint: {
    }
  });

// 1. Incluir el módulo
  grunt.loadNpmTasks('grunt-contrib-jshint');  
// 2.  Registrar la tarea
  grunt.registerTask("default", ['jshint']);
};

Incluir el módulo y registrar la tarea.

Configurar la tarea jshint

Las opciones de jshint son muchas. Se encuentran agrupadas en tres secciones generales:

  1. Forzar opciones – Enforcing Options -: Cuando alguna de estas opciones se establece como verdadera – true – esto hará que JSHint muestre más advertencias acerca de tu código.
  2. Relajar opciones – Relaxing Options -: Cuando alguna de estas opciones se establece como verdadera – true – esto hará que JSHint muestre menos advertencias acerca de tu código.
  3. Ambiente – Environment -: Estas opciones permiten especificar a JSHint que se van a utilizar algunas variables globales predefinidas.

Forzar Opciones

Algunas de las opciones de esta sección que podemos configurar son:

Opción

Descripción

bitwise

Esta opción prohibe el uso de operadores de bit a bit como ^ (XOR), | (OR), & (AND), etc.

curly

Esta opción requiere que siempre se utilicen llaves {} alrededor de los bloques en ciclos y condicionales.

eqeqeq

Esta opción prohibe el uso de igualdad (==) y no igualdad (!=) para utilizar identidad === y no identidad (!==).

es3

Esta opción indica que el código se necesita adherir a la especificación de ECMAScript 3. Útil si el código se va a ejecutar en navegadores antiguos – en especial Oldie – o en otro contexto de legado de JavaScript.

freeze

Esta opción prohibe que se sobrescriban – extiendan – prototipos de objetos nativos como Array, Date, entre otros.

immed

Esta opción prohibe el uso de IIFE sin envolverlas en paréntesis. El envolver la función en paréntesis ayuda a los lectores de código a entender que la expresión es el resultado de la función y no la función como tal.

latedef

Esta opción prohibe el uso de una variable antes de que fuera definida.

quotmark

Esta opción refuerza la consistencia en las comillas utilizadas en el código.
Acepta tres valores: true si no se quiere forzar un estilo en particular, “single” si únicamente se permiten comillas simples y “double” si únicamente se permiten comillas dobles.

undef

Esta opción prohibe el uso explícito de variables no declaradas.

Relajar opciones

Algunas de las opciones de esta sección que podemos configurar son:

Opción

Descripción

asi

Esta opción elimina las advertencias acerca de puntos y comas faltantes – al terminar sentencias de javascript -.

eqnull

Esta opción elimina las advertencias acerca de comparar valores con null – == null -. Estas comparaciones pueden resultar útiles si se quiere revisar si una variable es null o undefined.

esnext

Esta opción le indica a JSHINT que tu código utiliza sintaxis de ECMAScript 6.

evil

Esta opción elimina las advertencias acerca del uso de eval. El uso de eval est desaconsejado porque hace que tu código sea vulnerable a distintos tipos de ataque, además de que hace más difícil que el intérprete de JavaScript lo pueda optimizar.

Ambiente

Algunas de las opciones de esta sección que podemos configurar son:

Opción

Descripción

browser

Esta opción define globales expuestas por los navegadores modernos como document, navigator incluyendo algunas de HTML5 como FileReader.

devel

Esta opción define globales que son utilizadas – generalmente – para depurar código: console, alert. Es buena idea no incluirlas en el código que se va a utilizar.

nonstandard

Esta opción define globales no estándares pero que son utilizadas como escape y unescape.

worker

Esta opción define globales disponibles cuando el código está siendo ejecutado dentro de un WebWorker.

La lista completa de opciones se puede consultar en: http://jshint.com/docs/options/.

Dentro del objeto jshint vamos a definir los archivos que se van a evaluar y la manera en que van a ser evaluados.

Para definir los archivos a evaluar utilizamos la propiedad files y le asignamos un arreglo como valor. Dentro del arreglo se puede escribir el nombre de un archivo, de varios archivos separados por comas, podemos utilizar * que se sustituye por cualquier carácter.

jshint: {
  files: ['js/demo.js'],
//   files: ['js/*.js'],
// Si queremos evaluar todos los archivos .js
// que se encuentran dentro de la carpeta js
}

Después de definir los archivos, definimos las opciones de cómo queremos evaluar el código:

  grunt.initConfig({ 
    jshint: {
      files: ['js/demo.js'],
      options: {
        // Prohibir use de operadores como ^, |, &
        bitwise: true,
        // Utilizar operadores de identidad === en lugar de operadores de igualdad ==
        eqeqeq: true, 
        // Utilizar llaves para definir bloques de código
        curly: true, 
        // No extender prototipos nativos
        freeze: true, 
        // Elegir un tipo de comillas para el texto
        quotmark: "double", 
        globals: {
          // El código se va a utilizar en el navegador -  DOM c / document -
          browser: true,
          // El código utiliza alert y console para enviar notificaciones
          devel: true
        }
      }
    }
  });

En los archivos de código que había escrito no tenían ningún error – el código escrito era bastante simple y no tenía mucha funcionalidad -. Por eso modifiqué e incluí algunas lineas de código en demo.js. Estas líneas de código no cumplen con las evaluaciones definidas en las opciones.

String.prototype.snake_case = function () {
  this.toLowerCase().replace(/ /gi, "_");
}

var titulo = document.getElementsByTagName("h1")[0];

function visualizar_contenido() {
  mensaje = titulo.textContent;
  if (mensaje == "prueba" | mensaje === 'test')
    alert("Utiliza otro mensaje");
  console.log(mensaje.snake_case());
}

titulo.addEventListener("click", visualizar_contenido);

var parrafo = document.getElementsByTagName("p")[0];

function actualizar_contenido() {
  parrafo.textContent = prompt("¿Nuevo contenido para el párrafo?");
}

parrafo.addEventListener("click", actualizar_contenido);

Archivo a evaluar.

Para evaluar los archivos definidos con las opciones que definimos ejecutamos la tarea jshint.

$ grunt jshint

# Si definimos la tarea jshint como predeterminada
# podemos ejecutar simplemente
# $ grunt

En el caso de que existan líneas de código no cumplan con las opciones que definimos, se visualiza en la línea de comandos la ubicación del código que no cumple con las opciones junto con un mensaje describiendo qué es lo que no se cumple.

Evaluar el código
Evaluar el código

Corregimos el código para que cumpla con las especificaciones.

function snake_case (text) {
  return text.toLowerCase().replace(/ /gi, "_");
}

var titulo = document.getElementsByTagName("h1")[0];

function visualizar_contenido() {
  mensaje = titulo.textContent;
  if (mensaje === "prueba" || mensaje === "test") {
    alert("Utiliza otro mensaje");
  }
    
  console.log(snake_case(mensaje));
}

titulo.addEventListener("click", visualizar_contenido);

var parrafo = document.getElementsByTagName("p")[0];

function actualizar_contenido() {
  parrafo.textContent = prompt("¿Nuevo contenido para el párrafo?");
}

parrafo.addEventListener("click", actualizar_contenido);

Evaluamos las modificaciones realizadas.

Código que cumple con las especificaciones
Código que cumple con las especificaciones

Aunque jshint nos puede ayudar a prevenir problemas potenciales, no sustituye la evaluación del código con librerías como jasmine o qUnit.

Puedes descargar el demo de jshint:

  1. demo-14: Dependencia de “grunt-contrib-jshint” en package.json
  2. demo-15: Configuración del archivo Gruntfile.js código mal escrito en demo.js

Para instalar las dependencias se teclea desde la carpeta del proyecto:

$ npm install