WordPress CS en VSCode

WordPress tiene recomendaciones sobre cómo se debe escribir el código tanto si es para el core como para plugins y themes e incluso para la documentación.

Como hay una gran cantidad de aspectos tratados por estas reglas y, a veces, las mismas son contra intuitivas o por lo menos van en contra de los usos y costumbres es necesario incluir herramientas en nuestro workflow que nos obliguen a seguirlas y nos marquen cuando nos olvidemos.

Primero, para todo el código en JavaScript trabajaremos con ESLint y el plugin homónimo para VSCode. Primero instalamos el paquete de reglas:

npm install --save-dev eslint-config-wordpress

Si no tenemos instalado eslint globalmente también tendremos que instalarlo.

Lo siguiente es crear el archivo de configuración y agregar lo siguiente:

{
  "extends": "wordpress"
}

En caso de trabajar en Windows y, dependiendo del editor y nuestra configuración, puede ser útil desactivar la regla que nos marca los saltos de línea incorrectos. WordPress espera que utilicemos \n y Windows utiliza \r\n:

{
  "extends": "wordpress",
  "rules": {
    "linebreak-style": "off"
  }
}

Con esto estaría la configuración de ESLint, ahora pasamos a VSCode. Buscamos el plugin ESLint y lo instalamos. Si no tenemos ninguna configuración u organización partícular debería funcionar out-of-the-box.

En caso de necesitar tunear la configuración para indicar otros path o ajustes, en el Summary del plugin están detalladas todas las configuraciones necesarias.

En lo que respecta a PHP la idea es utilizar PHP Code Sniffer y el plugin phpcs. Nuevamente, arrancamos instalando todo con Composer:

composer require --dev squizlabs/php_codesniffer wp-coding-standards/wpcs

A continuación tenemos que indicarle a PHP Code Sniffer donde encontrar las reglas que instalamos:

./vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs

Ahora, en VSCode buscamos e instalamos el plugin phpcs y lo configuramos ya sea a través de la interfaz o editando el settings.json:

{
  "phpcs.enable": true,
  "phpcs.standard": "WordPress-Core",
}

Con respecto al standard tenemos 4:

  • WordPress-Core: Conjunto principal de reglas establecidos para codificar en PHP para WordPress.
  • WordPress-Docs: Reglas que abarcan todo lo relacionado con la documentación de código PHP.
  • WordPress-Extra: Un superconjunto que incluye a WordPress-Core y lo extiende agregando reglas que fomentan buenas prácticas que no están contempladas en los estándares de WordPress.
  • WordPress: El superconjunto que incluye todos los ruleset antes mencionados.

A menos que estemos contribuyendo directamente con WordPress me quedaría con el WordPress-Core o WordPress-Extra para evitarnos el rollo de la documentación que por momentos llega a ser barroca.

Existen, también, reglas para la correcta escritura del HTML y los stylesheet. En el primer caso la recomendación oficial va por el uso del W3C Validator y en el otro hay un conjunto de reglas para stylelint pero, por ahora, no lo utilicé nunca así que queda para otro momento esa parte.

Docker Compose: .env

Compose nos permite una gran personalización mediante el archivo de configuración pero hay algunas cosas que no están soportadas dentro del mismo. Para algunas de estas configuraciones existen parámetros que se pueden establecer en la línea de comando o mediante variables de entorno.

Estas formas son poco prácticas porque implican acordarse los parámetros o nombres de las variables y siempre están sujetas al riesgo de los errores de tipeo. Por suerte, Compose, automáticamente levanta el archivo .env y establece las variables durante el tiempo de ejecución.

Hay que tener en cuenta que estas variables no son visibles para los contenedores sino para Docker Compose.

Hay varias, pero las más interesantes son:

  • COMPOSE_PROJECT_NAME: Permite establecer el nombre del proyecto. Esta cadena es la que usa Docker Compose como prefijo al momento de crear los containers. Por defecto utiliza el nombre de la carpeta actual.
  • COMPOSE_FILE: Para poder indicar el nombre del archivo de configuración que utilizará Docker Compose. Sirve para poder tener configurados distintos entornos ,por ejemplo, para desarrollo y para testing. Por defecto, docker-compose.yml.
  • DOCKER_HOST: En caso de que queramos utilizar el servicio de docker de un host remoto. Por ejemplo, tcp://192.168.0.13:2375. El valor por defecto apunta al socket local.
  • DOCKER_TLS_VERIFY: Si es necesario utilizar TLS para conectarse al servicio de Docker, alcanza con establecer a cualquier valor aunque generalmente se establece a 1. Si no hace falta utilizar TLS no hay que setear la variable porque cualquier valor (incluidos vacio, cero, false, étc) van a habilitarlo.
  • DOCKER_CERT_PATH: Si vamos a utilizar TLS vamos a necesitar certificados. Por defecto busca los archivos ca.pem, cert.pem y key.pem en la carpeta ~/.docker pero podemos establecer la que más nos convenga.

Docker: WordPress

Siguiendo con el tema de Docker, uno de mis usos preferidos es utilizarlo para crear entornos locales para testear WordPress. Si bien hay una imagen oficial de WordPress para Docker su configuración out-of-the-box necesita algunos ajustes para sernos de utilidad.

Primero, el archivo docker-compose.yml:

version: "3"

services:
  mysql:
    image: mysql:5.7
    restart: "no"
    volumes:
      - ./wordpress/database:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - mysql
    image: wordpress
    ports:
      - 8080:80
    restart: "no"
    volumes:
      - ./wordpress/content:/var/www/html/wp-content
      - ./wordpress/.htaccess:/var/www/html/.htaccess
      - ./wordpress/php.ini:/usr/local/etc/php/conf.d/wordpress.ini
      - <build dir>:/var/www/html/wp-content/themes/<theme name>
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DEBUG: 'true'

  adminer:
    depends_on:
      - mysql
    image: adminer
    restart: "no"
    ports:
      - 8000:8080
    environment:
      ADMINER_DEFAULT_SERVER: mysql

Como vemos, trabajo con 3 images: mysql, wordpress y adminer.

En la primera, mysql, creo un volumen que apunta a ./wordpress/database en el host y a /var/lib/mysql en el container lo que me permite persistir la información de la base de datos mediante el sencillo proceso de almacenar los archivos de datos de MySQL en el host. Es importante que especifiquemos la versión de MySQL en vez de usar latest, para evitar que los datos se pierdan al actualizarse el servidor.

La segunda, wordpress, tiene 4 volumenes creados:

  • ./wordpress/content, nos permite persistir plugins, themes, actualizaciones, étc.
  • ./wordpress/.htaccess, nos sirve para poder trabajar con el .htaccess de WordPress. En mi caso lo utilizo para redirigir las solicitudes a la carpeta uploads al servidor de producción para no tener que replicarla cada vez que creo un container para hacer pruebas.
  • ./wordpress/php.ini, nos da la posibilidad de configurar algunos parámetros de PHP. Son de particular interés el tamaño máximo de los uploads y el tiempo de ejecución ya que los por defecto son muy chicos.
  • <build dir>, este es el directorio donde se encuentra la build del theme (o plugin) con el que estemos trabajando.

Con respecto a las configuraciones, si no hicimos ningún cambio en las variables de la BBDD, no hace falta tocarlas. Si no necesitamos que esté activado el debug podemos borrar la susodicha configuración o ponerla en ‘false’.

adminer, necesario para poder trastear con la BBDD. La única configuración que pasamos es más un QOL que otra cosa y sirve para establecer el servidor por defecto.

Una cosa importante a tener en cuenta es que, como Docker crea las carpetas correspondientes a los volúmenes con el usuario root, tenemos que cambiar el owner por el usuario www-data. Para esto, una vez creado los container, alcanza con ejecutar el siguiente comando:

docker-compose exec wordpress chown www-data:www-data /var/www/html/wp-content /var/www/html/wp-content/themes

Por último dejo el archivo .htaccess y php.ini que utilizo con las características antes comentadas:

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteBase /
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{HTTP_HOST} ^localhost:8080$
  RewriteRule ^wp-content/uploads/(.*)$ https://server/wp-content/uploads/$1 [NC,L]
</IfModule>
file_uploads = On
memory_limit = 64M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 600

Docker

Hace unos meses como consecuencia de haber tenido que cambiar de discos en mi PC me encontré con la necesidad de volver a montar un entorno local de desarrollo. Como buen programador, decidí que montar todo igual que antes era demasiado sencillo y decidí revisar desde cero mi stack.

El primer cambio importante fue el abandonar Windows 10 + WSL por Ubuntu 18.04. Hay dos razones principales para esta decisión: la velocidad de I/O y los contenedores. Ya sea por el manejo de la fragmentación o falta de DNLC, los problemas de NTFS con los directorios con gran cantidad de archivos son históricos y agregarle una capa más de abstracción como es el subsistema de Linux no ayuda. Si agregamos que WSL no soporta cgroups por lo que no nos permite ejecutar nativamente containers el salto de un SO a otro es un paso lógico.

Anteriormente tenía en Windows instalado XAMPP y mediante el uso de junctions, el archivo hosts y algunos truquillos más codeaba en VSCode, utilizaba Webpack, Gulp, étc en WSL y visualizaba en un navegador en Windows.

Este workflow funcionaba en general bastante bien pero presentaba una rigidez notable y era poco práctico para testear cosas nuevas. Por esto, con el paso a Linux, la instalación de un sistema de gestión de contenedores era un must. La opción inicial era LXD pero este resultó estar más orientado a contenedores de SO que de aplicaciones. Si bien da mucha más flexibilidad para la configuración implica también más intervención del usuario mientras que Docker agrega una capa de abstracción que automatiza mucho de estos procesos lo que se adaptaba mejor a mis necesidades.

Primeras impresiones

Docker Compose es, diría, indispensable para el uso diario de Docker. Un simple archivo yaml permite configurar en unas pocas líneas una aplicación de múltiples contenedores.

En un principio el sistema de imágenes parece poco personalizable hasta que se descubre la posibilidad de montar «volúmenes» que, a los efectos prácticos, no son más que los tradicionales soft links entre el host y el contenedor. Esta posibilidad de compartir archivos y directorios nos permite, por ejemplo, externalizar en un repositorio git los archivos de configuración para mantenerla fácilmente sincronizada. O hacer lo mismo con la carpeta de datos de MySQL para volver los mismos persistentes entre distintos contenedores o replicar fácilmente la BBDD en producción.

La suma de los dos puntos anteiores vuelve el montar sistemas de prueba algo eficiente y completamente automatizable lo que repercute mucho en las ganas de hacer y usar los tests y sus beneficios asociados.

Habiendo trabajado antes con VM las diferencias de uso de recursos y tiempo de warm up y mantenimiento con Docker son bastante grandes. La configuración de los network bridge son un problema que queda en manos de Docker liberándonos de una tarea, por lo menos en desarrollo, que suele mostrarse por demás conflictiva. Esto no significa que no podamos trabajar con redes pero si que no es necesario hacerlo con Docker out-of-the-box en entornos privados.

Los repositorios públicos de imágenes son uno de los fuertes de Docker. Hasta el momento no me pasó de encontrarme sin una aplicación que necesitara y no tuviera su respectiva imagen.

Limitaciones

Como siempre, no todo es un camino de rosas y Docker presenta algunas limitaciones y problemas que pueden hacer que nos agarremos la cabeza hasta que le encontremos la vuelta para evitarlos.

Si bien Docker, y los containers en general, son una gran mejora sobre las VM todavía presentan un overhead que para los costes de servidor en el tercer mundo son demasiado altos por lo que por ahora el deploy va a seguir siendo bare metal o VPS.

El manejo de permisos de los volumenes es complejo, a los efectos prácticos estamos compartiendo archivos y carpetas entre dos SO diferentes, con usuarios diferentes. Sumado a eso, por defecto, los comandos se ejecutan como root dentro de los containers y, por lo tanto, los archivos creados por esos comandos suelen pertenecer al mismo usuario y grupo mientras que los que creamos en el host suelen tener permisos para nuestro usuario.

Todo en Docker está pensado para ocultar las complejidades del manejo de contenedores y esto inevitablemente nos lleva a soslayar los problemas de seguridad. Por ejemplo, por defecto, los containers no tienen ningún límite a los recursos que pueden utilizar; como siempre que utilizamos recursos públicos, únicamente un análisis de seguridad o usando self baked images nos podemos asegurar que no estemos utilizando una rogue image con backdoors; étc.

Trucos y consejos

En Linux los permisos se manejan con el UID y el GID, no con el nombre de usuario y grupo. Si en nuestro container el id de www-data coincide con el de nuestro usuario en el host, el manejo de permisos se vuelve más sencillo. Este truco es conocido por los que usan Docker hace más tiempo e incluso algunas imágenes, como la de PHP, lo soportan por defecto.

Este es más un truco de Bash que de Docker pero igualmente útil. Muchas veces necesitamos trabajar con todos los containers activos lo que es sumamente engorroso porque implica ejecutar docker por cada container. Para evitar esto podemos utilizar la sustitución de comandos de Bash de la siguiente forma:

docker stop $(docker ps -q)

Este comando va a ejecutar stop en todos los containers activos.

Para poder ver en tiempo real los logs de un container de Docker (o de varios si usamos Docker Compose):

docker logs -f <contenedor>

Hacer y restaurar backups de nuestros container es muy sencillo:

# Hacer el backup del contenedor a una imagen
docker commit -p <container id> <image name>

# Exportar la imagen a un archivo
docker save -o <filename.tar> <image name>

# Restaurar una imagen a partir de un archivo
docker load -i <filename.tar>

# Restaurar (crear) un contenedor a partir de la imagen
docker run <image name>

Por último, el parámetro ports de Docker Compose sirve para exponer puertos del container en el host pero su formato en vez de ser origen:destino como resulta intuitivo es exactamente al revés. Nada que sea complicado pero recordarlo evitará darnos la cabeza contra la pared cuando no sepamos por qué no funciona nuestro container.

TDD WordPress Theme

Tanto al comenzar a desarrollar un tema desde cero como cuando ya adquirió mayor complejidad tenemos que hacer una serie de chequeos de forma manual para asegurarnos que no nos olvidamos de incluir ninguna funcionalidad o no quedó código muerto.

Obviamente una buena checklist y una organización bien planificada de nuestro código simplifica mucho el tema pero siempre es menester automatizar este tipo de tareas.

WordPress provee una Test Suit pero está orientada principalmente al testeo del funcionamiento de WordPress más que a las cuestiones atinentes al desarrollo de themes.

Si bien puede ser utilizada como base para testear nuestros temas, a mi entender, agrega demasiado overhead para lo que nos aporta. Partiendo de este presupuesto decidí comenzar a desarrollar algunos tests propios con PHPUnit.

Primeramente, basado en el checklist que antes mencioné, definí una serie de chequeos que me interesa automatizar:

  • Existe los archivos functions.php, style.css y el screenshot
  • No hay archivos sin usar
  • Existe el template correspondiente a los template tags usados. Por ej.: get_header y header.php
  • Todas las uris locales son relativas
  • Todos los scripts/styles registrados son usados y existen
  • Hay sidebars y todas son usadas en algún lado
  • Todos los espacios de menu son usados en algún momento
  • Las páginas/artículos y el sitio tienen metadatos
  • El favicon está definido y la ruta existe
  • El theme no tiene que tomar funciones de plugin:
    • Dashboard widgets
    • Custom Post Types
    • Custom Taxonomies
    • Shortcodes
    • Metaboxes
    • Social integrations
    • Bloques de Gutenberg
  • La paginación respeta la configuración de Ajustes > Lectura
  • Customizer sanitization
  • Scripts/styles externos cargados de forma agnóstica
  • No se usa @import en los stylesheet
  • Soporte para title tag
  • Uso de $content_width
  • CSS básicos definidos:
    • alignleft, aligncenter, alignright,
    • wp-caption,
    • size-full, size-large, size-medium, size-thumbnail
  • Uso de WP_Filesystem en vez de las PHP File Functions: mkdir, fopen, fread, fwrite, fputs
  • Sin estilos o scripts hardcodeados
  • Scripts cargados únicamente en footer
  • i18n

A primera vista, algunos son sencillos como la verificación de la existencia de archivos, otros van a requerir análisis del código y algunos que podrían ser verificados utilizando la API que trae WordPress contra un servidor de desarrollo o staging.

Por ahora voy a ir haciendo el desarrollo y pruebas contra la copia de desarrollo del theme de un sitio que está en producción para tener un objetivo más real aunque la idea sería, a largo plazo, constituir un repositorio agnóstico que pueda ser rápidamente clonado en nuestro proyecto.

La primera aproximación quedaría con la siguiente estructura dentro de mi workflow habitual:

  • tests/bootstrap.php
  • tests/FaviconTest.php
  • tests/MissingFilesTest.php
  • tests/StylesheetTest.php
  • composer.json
  • phpunit.xml

Y el código propiamente de cada archivo sería:

Próximamente estaré publicando más novedades.

Recursos útiles para el desarrollo web

Serie de herramientas y bibliotecas online que son útiles durante el proceso de desarrollo web.

Google Analytics

Podemos usar otro pero definitivamente este es el gestor de estadísticas gratuito más completo. Información en tiempo real e histórica sobre los horarios de acceso, distribución geográfica, origen, étc. Y, más interesante al momento de pensar la, datos sobre el tipo de dispositivos usados para conectarse (mobile, tablet o desktop), el navegador o la resolución de pantalla. Por último, si tenés instalado el plugin (ahora sin soporte pero todavía funcional) podés incluso analizar el click heatmap de tu sitio.

Can I Use

Una vez que ya sabemos todo sobre los dispositivos que los usuarios van a usar para conectarse al sitio, es momento de empezar a delimitar las tecnologías que vamos a tener disponibles. En 10 años Can I Use se ha vuelto el standard de facto para obtener este tipo de información. Alcanza con ingresar en el buscador el nombre de la tecnología, un comando o etiqueta relacionado y tendremos información sobre el soporte por versión en los distintos navegadores, el uso relativo de los mismos y notas al pie sobre cosas a tener en cuenta.

MDN Web Docs

Definidas las tecnologías empieza el momento de picar código y comienzan, también las dudas que si un checkbox lanza un evento click o un change, que cual era el comando para agregar un elemento al principio de un Array, étc. Mientras más tecnologías están involucradas en el desarrollo web más difícil es acordarse al dedillo de todo y ahí entra a jugar MDN Web Docs una de las referencias más completas en el tema.

CSS-Tricks

Si bien MDN Web Docs tiene un apartado para CSS, la autoridad en el tema es de CSS-Tricks. Desde snippets a, como su nombre lo indica, trucos y consejos relacionados con el uso de los estilos y una galería de ejemplos de los más interesantes.

CSS Triggers

Una vez que ya empieza a tomar forma el sitio, empezamos a agregar más interactividad al mismo mediante la captura de eventos y manipulación del DOM. Estas modificaciones del modelos de objetos repercuten directamente en el CSSOM y pueden implicar un reflow, un repaint o un relayout cada uno con sus respectivas demoras. Cuando necesitamos saber si es mejor usar transform o modificar directamente el width de un objeto ahí entra CSS Triggers para no equivocarse.

Regular Expressions 101

Hablando de tópicos donde hace falta un ayuda memoria, llegamos a las expresiones regulares. Karma de muchos programadores, Regular Expressions 101 trae tanto una referencia como un entorno de pruebas para poder generar ese pattern perfecto.

Debuggex

Ya ni nos acordamos que matchea ese pattern que tenemos delante o estamos leyendo código de otra persona y vamos medio perdidos nada mejor que Debuggex, un tester visual que nos permite ver de qué va la cosa.

CSS Stats

Recién habíamos terminado de armar todo cuando el cliente nos pidió «unos pocos cambios, algo acá y allá» o llevamos tiempo en producción y hasta el hijo de la vecina, «que sabe un poco de computadoras», metió mano. Por lo que sea terminamos con 402 colores únicos o 12k de reglas y no lo sabemos. Llevar un buen control sobre la situación de nuestros archivos de estilo es una tarea que se ve tremendamente simplicada con CSS Stats.

Pingdom

Siguiendo en la línea de controlar la performance del sitio, entramos en el área de las herramientas más generales como Pingdom que nos provee rápidamente con un resumen de la situación general. Vistoso por demás, también resulta útil para «robar» algunos gráficos para presentar al cliente.

WebPagetest

Lo que Pingdom tiene de bonito, WebPagetest lo tiene de detallado. Nunca lo vamos a usar como imagen en un Power Point pero si necesitamos estadísticas precisas para ver dónde está el cuello de botella en la carga o qué script está consumiendo demasiado tiempo este sitio nos va a permitir encontrar la información que buscamos.

WordPress y PHPUnit

PHPUnit es uno de los frameworks para test unitarios automáticos para PHP más usados y el elegido por los desarrolladores de WordPress junto con QUnit para probar la plataforma. Para facilitar las pruebas, los desarrolladores han creado ya todo un conjunto de test y clases auxiliares que nos resultarán muy útiles en nuestro workflow.

Instalación

Primero, necesitamos instalar PHPUnit en su versión 6 ya que la 7 no es soportada por WordPress. Hay distintas formas documentadas en el sitio del framework y podemos elegir la que más se adapte a nuestro entorno.

Segundo, creamos una nueva base de datos separada para los tests porque que la suite va a borrar todos los datos de las tablas de la instalación donde se ejecute.

Tercero, no es necesario pero definitivamente es la mejor forma de manejar el entorno de pruebas vamos a instalar wp-cli. Nuevamente, hay varías formas de llevar adelante la tarea y va a depender de nuestro entorno el método que elijamos.

Por mi parte, me ha dado mejores resultados la instalación recomendada: descargar el .phar, darle permisos de ejecución y ponerlo en una carpeta que esté en PATH.

Cuarto, nos situamos en la carpeta de la instalación de wordpress para utilizar las opciones del paquete scaffold de wp-cli para generar los archivos necesarios para instalar los tests según sea un plugin o un theme.

wp scaffold plugin-tests <nombre plugin>
wp scaffold theme-tests <nombre theme>

Quinto, ejecutamos el archivo generado dentro de la carpeta del plugin/theme en el paso anterior para instalar el entorno de pruebas. Vamos a necesitar las credenciales y datos de acceso a la base de datos que creamos antes.

bin/install-wp-tests.sh <nombre bbdd> <usuario> <contraseña> <host>

Con esto queda todo listo para que empecemos a desarrollar nuestros tests y ponerlos en la carpeta homónima para que PHPUnit los encuentre.

Para más información sobre los unit test en WordPress estos artículos van a dar una idea de las posibilidades:

Workflow en WordPress

La estructura de directorios que uso en mi workflow se aprovecha de una feature de WordPress que permite distribuir grupos de themes. La idea es que en vez de almacenar un theme por directorio se puedan poner varios usando subdirectorios.

El funcionamiento de esta feature es bastante sencillo, cuando WP lista las carpetas en wp-content/themes para ver que themes hay instalados, revisa si en la raíz  de las mismas está el archivo style.css; si no lo encuentra busca en los subdirectorios de primer nivel de la misma por si es un grupo de themes.

La idea entonces es que en nuestro entorno de desarrollo ese subdirectorio, que WP va a identificar como el que contiene el theme, sea el de las builds y que cualquier otro subdirectorio de primer nivel no tenga un archivo style.css.

  • build
  • dist/theme
  • src
    • images
    • languages
    • scripts
      • admin
      • customize
      • modules
    • styles
    • templates
      • admin
      • customize
      • modules
    • vendor
  • tasks

Build y Dist

Como se deduce de sus nombre, build, contiene las builds con todo el código sin comprimir y preparado para debug mientras que en dist se guarda el theme listo para producción.

Para evitar confundir a WP, es importante que en la raiz del directorio dist no se encuentre el style.css sino en un subdirectorio de este. Esto, además, nos simplifica el proceso de crear el zip / tar.gz para distribuir porque ya nos queda todo en un directorio listo para comprimir.

Src

Los «fuentes» del theme en el que estamos trabajando: php, imágenes y scss sin procesar, archivos de traducción, étc. Casi todo lo que está en este directorio va a ser procesado, optimizado, comprimido y demás operaciones que van a dar como resultado nuestro theme.

La idea original del directorio images era, justamente, guardar imágenes que se usaran en el diseño del theme pero, hoy en día, con los avances de CSS únicamente almacena el screenshot.

La carpeta templates contiene todo el código php, el ordenamiento interno tiene que cumplir con las limitaciones y recomendaciones de cualquier theme.

Me gusta mucho trabajar con el customizer así que suelo generar bastante código para este y, por lo tanto, tanto en la carpeta de scripts como de templates lo guardo en un directorio separado.

Además, a lo largo del tiempo, he creado algunos snipets de código que utilizo tan habitualmente como preload y lazyload, google fonts, étc que los mantego de forma separada y que cuando los incluyo en un proyecto los guardo en la carpeta modules.

Por una cuestión de separación también guardo en otro directorio, admin, todo el código que está pensado únicamente para ejecutarse en el dashboard de WP.

Por último, como no siempre hay paquetes con la librería que necesito, la versión que busco o no quiero usar un CDN, o por lo que sea, tengo el directorio vendor que se copia íntegramente tanto a las build como a la dist.

Tasks

Las tasks de Gulp.js: build, clean, clean-vendor, images, scripts, styles, templates, translation, vendor, watch.

Mantengo separadas las partes de código propio del código de vendor: build y clean para uno y vendor y clean-vendor para el otro. Ídem con las traducciones: translation.

Normalmente, build se encarga tanto de generar tanto la versión de pruebas como la versión para distribución. Antes las generaba con tareas específicas pero siempre se terminaban dando dos escenarios: dos tareas muy parecidas que había que mantener sincronizadas manualmente o una tarea con un montón de código duplicado y un enredo de condicionales.

La más importante de las tareas es watch que monitorea los cambios y actualiza la build. Para esto utilizo el modulo que trae Gulp por defecto en conjunto con BrowserSync para la inyección del nuevo CSS pero sin actualización automática. Pero, cuando trabajo sobre el customizer, desactivo completamente BS porque no se llevan bien y se suele quedar con pantallas en blanco u errores.

Gists

WP_Deduplicator: Clase estática que permite llevar el control de los post mostrados para evitar duplicar el contenido.

WP_Keepalive: Función que agrega o modifica la cabecera Connection para informar al cliente que es posible reutilizar la conexión abierta ahorrándonos establecer una conexión nueva para cada archivo.

WP_Clipboard: Función que usa una lista blanca para filtrar las etiquetas HTML del texto que se pega en el editor.