Diseccionando un Drupal Theme

1. Temas predeterminados vs temas personalizados

Tenemos un par de opciones cuando se trata de qué temas queremos usar en Drupal 8, temas predeterminados, como Bartik y Seven, o temas personalizados creados por un diseñador. Ambos son similares en estructura y configuración, pero la separación principal comienza en la estructura de directorios.

1.1. Estructura de directorios y convenciones de nomenclatura

En Drupal 8 la estructura de carpetas se cambia para hacerlo más lógico. Todo que se envía con Drupal ahora reside en una carpeta central que incluye los temas predeterminados, que ahora se encuentran dentro de la carpeta core/themes. Sin embargo, cualquier tema que descarguemos o desarrollemos ahora reside en la carpeta /themes.

La estructura de la carpeta comprende los siguiente:

  • Temas predeterminados: estos temas residen en /core/themes e incluyen Bartik, Classy, Seven, Stable y Stark.

  • Temas personalizados: estos temas residen en el directorio /themes y contendrán cualquier tema contribuido o personalizado.

Antes de que podamos comenzar a crear nuestros propios temas personalizados, necesitamos tener una mejor comprensión de cómo se configuran los temas y cómo le permiten a Drupal saber exactamente dónde mostrar contenido y cómo debería verse el contenido.

1.2. Administrar la configuración en Drupal 8

La configuración del tema en Drupal 8 ahora ha adoptado YAML. YAML es un estándar de serialización de datos amigable para el ser humano utilizado por muchos lenguajes de programación, incluido Symfony, en el que Drupal 8 está ahora integrado.

Con esta adopción, la sintaxis para crear un archivo de información también ha cambiado. Un concepto importante al crear o editar cualquier archivo *.yml es que se requiere una sangría adecuada. Si no se ajusta correctamente la configuración, pueden producirse errores o que la configuración no se cargue. Podemos bucear más profundo en los detalles de YAML y encontrar información más detallada en: http://symfony.com/doc/current/components/yaml/yaml_format.html

2. Revisando el nuevo archivo info.yml

El archivo info.yml es obligatorio al crear cualquier tema. Ayuda a notificar a Drupal que existe un tema y proporciona información a la interfaz de Apariencia de que un tema está disponible para su instalación.

Trabajaremos con los archivos *.info.yml al crear nuestro primer tema, así que echemos un vistazo a la composición de un archivo básico de example.info.yml:

name: Example

description: 'An Example theme.'

type: theme

package: Custom

base theme: classy

core: 8.x

libraries:

- example/global-styling

regions:

header: Header

primary_menu: 'Primary menu'

secondary_menu: 'Secondary menu'

page_top: 'Page top'

page_bottom: 'Page bottom'

highlighted: Highlighted

breadcrumb: Breadcrumb

content: Content

sidebar_first: 'Sidebar first'

sidebar_second: 'Sidebar second'

footer: 'Footer'

A primera vista, el archivo example.info.yml es lógico en estructura y sintaxis. Comenzando desde arriba y yendo hacia abajo, el archivo se divide en diferentes secciones de metadatos que contienen información general, bibliotecas y regiones. Esta información se describe utilizando el formato clave: valor.

Deberíamos comenzar por entender cómo funcionan los metadatos básicos.

3. Metadatos

Los metadatos contenidos en cualquier archivo de temas *.info.yml ayudan a describir qué tipo de documento es. En nuestro caso, comienza a describir un tema, incluido el nombre, la descripción y la versión de Drupal con la que trabaja el tema. Se requieren algunos metadatos para que el tema funcione correctamente, así que exploremos las claves en más detalle:

  • name (obligatorio): es el nombre del tema.

  • type (obligatorio): es el tipo de extensión (tema, módulo o perfil).

  • Base theme (obligatorio): es el tema que hereda el tema actual. En la mayoría de casos, se recomienda que haga referencia a Classy o Stable como tema base. Si elegimos no hacer referencia a un tema base, tendremos que establecer el valor en FALSE.

  • Description (obligatorio): es la descripción del tema.

  • Package (opcional): se usa para agrupar archivos similares al crear módulos.

  • Version (opcional): esto se crea al empaquetar el script.

  • Core (obligatorio): especifica la versión de Drupal con la que es compatible el tema.

Uno de los errores más comunes al crear por primera vez un archivo *.info.yml es olvidarse de cambiar el valor de core a 8.x. Si no se establece este valor, el tema no se mostrará en la interfaz Apariencia.

La siguiente sección de un archivo *.info.yml nos permite administrar recursos (CSS o JS) utilizando el nuevo concepto de bibliotecas.

4. Bibliotecas

Drupal 8 introduce una novedad, el principio de alto nivel para administrar los recursos utilizando un archivo de configuración de bibliotecas que puede cargarse globalmente o por página. Este concepto ayuda a mejorar el rendimiento del frontend y a garantizar que cualquier dependencia que un recurso en particular necesite se cargue correctamente. Una ventaja de esto es que jQuery ya no se carga en cada página como lo hizo en versiones anteriores.

El concepto de un archivo de configuración *libraries.yml también significa que ya no existen las propiedades de las hojas de estilo y las secuencias de comandos con las que hemos estado familiarizados en Drupal 7. En cambio, el proceso para administrar recursos incluye guardar cualquier archivo CSS o JS en la carpeta css o js de nuestro tema y luego definir un archivo de biblioteca que haga referencia a los archivos que queremos usar en nuestro tema.

4.1. Definiendo una biblioteca

Al definir un archivo *libraries.yml para un tema, cada biblioteca hará referencia a la ubicación de archivos CSS o JS individuales y se organizará mediante la categorización de estilos SMACSS (https://smacss.com/).

  • Base: esto define el restablecimiento/normalización de CSS más el estilo del elemento HTML.

  • Layout: define la disposición macro de una página web, incluido cualquier sistema de cuadrícula.

  • Component: define los elementos de IU discretos y reutilizables.

  • State: define los estilos que se ocupan de los cambios del lado del cliente en los componentes.

  • Theme: este es un estilo puramente visual para un componente.

En la mayoría de los casos, una simple referencia de biblioteca seguirá la categorización del tema. Por ejemplo, si quisiéramos crear un archivo example.libraries.yml que incluyera recursos para CSS y JS, crearíamos una biblioteca que apuntara a nuestros recursos, como se muestra aquí:

libraryname:

  css:

    theme:

      css/style.css: {}

      css/print.css: { media: print }

  js:

    js/scripts.js

Luego, haríamos referencia a la biblioteca dentro de nuestra configuración de ejemplo.info.yml simplemente agregando lo siguiente:

libraries:

  - example/libraryname

Esto daría como resultado que Drupal agregara a cada página los archivos CSS y JS contenidos en nuestra biblioteca. Donde esto se vuelve poderoso es en la administración de recursos, ya que solo necesitaríamos hacer modificaciones a nuestro archivo example.libraries.yml si alguna vez necesitamos agregar o eliminar recursos.

4.2. Anulación de bibliotecas

Las bibliotecas también pueden anularse para modificar los recursos declarados por otras bibliotecas, posiblemente agregados por un tema base, por un módulo o incluso por el núcleo de Drupal. La capacidad de anular las bibliotecas incluye eliminar y reemplazar recursos por completo. De la misma forma que hacemos referencia a una biblioteca de nuestro archivo *.info.yml, podemos anular las bibliotecas agregando lo siguiente:

libraries-override:

# Replace an entire library.

core/drupal.vertical-tabs: example/vertical-tabs

# Replace an asset with another.

core/drupal.vertical-tabs:

css:

component:

misc/vertical-tabs.css: css/vertical-tabs.css

# Remove an asset.

core/drupal.vertical-tabs:

css:

component:

misc/vertical-tabs.css: false

# Remove an entire library.

core/modernizr: false

En este caso, la configuración de anulación de bibliotecas logra algo diferente para cada línea. Ya sea que esté reemplazando una biblioteca completa o eliminando un activo, ahora tenemos la flexibilidad para controlar los recursos como nunca antes.

4.3. Ampliar bibliotecas

Las bibliotecas también se pueden ampliar para permitir el reemplazo de CSS agregado por otra biblioteca sin modificar los archivos originales. Esto se puede hacer agregando lo siguiente a nuestra configuración *.info.yml de la siguiente manera:

libraries-extend:

  core/drupal.vertical-tabs:

    - example/tabs

En este caso, la configuración de libraries-extend extiende el propio archivo core.libraries.yml de Drupal y extiende la biblioteca drupal.vertical-tabs con un estilo adicional.

Si bien ahora tenemos una comprensión general de cómo se definen, sobreescriben y amplían las bibliotecas, solo hemos tratado con bibliotecas cargadas globalmente en nuestra instancia de Drupal utilizando nuestro archivo de configuración. Sin embargo, hay dos métodos más para incluir recursos dentro de una página directamente, sin necesidad de agregarlo a cada página.

4.4. Adjuntar una biblioteca

En muchos casos, podemos estar desarrollando alguna funcionalidad CSS o JS que es específica de una página individual. Cuando se nos presenta este requisito, tenemos la capacidad de adjuntar una biblioteca a una página usando dos métodos diferentes.

A) Usando Twig para adjuntar una biblioteca

Si bien vamos a aprender todo sobre Twig un poco más adelante en el capítulo, tenemos que hacer una pausa para hacer referencia a una función de Twig llamada {{ attach_library() }}.

Esta función nos permite agregar a cualquier plantilla de Twig una biblioteca que puede incluir CSS o JS que se cargarán solo en esa página.

Por ejemplo, si quisiéramos agregar Slick Carousel (http://kenwheeler.github.io/slick/) a nuestra página, podemos definir la biblioteca dentro de nuestro archivo example.libraries.yml de la siguiente manera:

# Slick

slick:

version: VERSION

css:

theme:

vendor/slick/slick.css: {}

js:

vendor/slick/slick.min.js: {}

dependencies:

- core/jquery

Entonces podríamos agregar lo siguiente a nuestra plantilla de Twig:

{{ attach_library('example/slick') }}

Esto nos proporciona algunas buenas funcionalidades para definir bibliotecas individuales para varias funciones de usuario y también para que esos activos se utilicen donde decidamos adjuntarlos.

B) Usar las funciones de preproceso para adjuntar una biblioteca

Otro método para adjuntar una biblioteca a una página individual depende de la creación de un archivo *.theme que nos permite usar funciones de preproceso para manipular variables de página. Aprenderemos mucho más sobre la creación de un archivo *.theme un poco más adelante, pero es importante tener en cuenta que podríamos adjuntar el mismo Slick Carousel a nuestra página sin llamarlo globalmente mediante el uso de una función de preproceso, como se muestra en el siguiente ejemplo:

function example_preprocess_page(&$variables) {

  if ($variables['is_front']) {

  $variables['#attached']['library'][] = 'example/slick';

  }

}

Aquí, estamos verificando si estamos en la página de inicio de nuestro sitio web y adjuntando nuestra biblioteca de Slick utilizando el array de biblioteca #attached. De nuevo, esto puede parecer un poco avanzado pero merece mencionarse.

La última sección que queremos cubrir cuando trabajamos con cualquier archivo *.info.yml es sobre regiones que se pueden definir para el diseño de nuestro tema.

5. Regiones

Las regiones desempeñan un papel fundamental en la tematización, ya que Drupal necesita saber exactamente dónde se puede mostrar el contenido. Esto tiene un impacto en qué regiones son visibles para el diseño de bloques. Si no especificamos ninguna región dentro de nuestro archivo *.info.yml entonces Drupal nos proporcionará regiones por defecto.

Si decidimos agregar regiones adicionales a nuestro tema, también debemos agregar las predeterminadas o de lo contrario no tendremos acceso a ellas.

Echemos un vistazo a cómo se implementa esto:

regions:

  header: Header

  primary_menu: 'Primary menu'

  secondary_menu: 'Secondary menu'

  page_top: 'Page top'

  page_bottom: 'Page bottom'

  highlighted: Highlighted

  breadcrumb: Breadcrumb

  content: Content

  sidebar_first: 'Sidebar first'

  sidebar_second: 'Sidebar second'

  footer: 'Footer'

El valor de cada clave es lo que se muestra en el diseño de bloques en la interfaz de administración y puede nombrarse como queramos. Podemos agregar regiones adicionales según nuestro tema requiera.

Ahora que hemos cubierto los aspectos básicos de la configuración del tema, es hora de que establezcamos un entorno de desarrollo local que nos permita trabajar con archivos y plantillas sin preocuparnos por tener que borrar el caché de Drupal o adivinar qué plantillas Twig están siendo utilizadas.

6. El papel de las plantillas en Drupal

Es posible que hayamos escuchado el término “plantilla” antes cuando hablamos con alguien sobre temas y sobre Drupal. Pero, ¿qué es exactamente una plantilla? Podemos pensar en una plantilla como un archivo de texto no diferente de cualquier documento HTML que proporcione un método para separar la capa de presentación de la lógica comercial. En los sitios web tradicionales de PHP, tenemos la capacidad de mezclar PHP con HTML y CSS, lo que hace que la administración de páginas web sea difícil y peligrosa. Drupal nos proporciona la capacidad de utilizar motores de plantillas para imponer la separación de los dos, entonces podemos comenzar a enfocarnos más en el HTML y CSS y preocuparnos menos por el PHP.

6.1. Como funcionan las plantillas

En general, las plantillas pueden contener marcas HTML y variables PHP que generan contenido en una base de datos Drupal. Las plantillas pueden ser tan pequeñas como unas pocas líneas de HTML que contienen la capa de presentación de un bloque que se muestra en una región de la página, o la propia página real, con contenedores definidos para encabezado, contenido, etc.

Para tener una mejor idea de cómo es esto, echemos un vistazo a la siguiente imagen:

Si dividimos la imagen en secciones lógicas de un sitio web, podemos comenzar a tener una idea de lo que constituye una plantilla. Una plantilla puede ser cualquiera de lo siguiente:

  • Contenedor HTML: contiene el marcado HTML de nivel superior, incluidos el título, los metadatos, las hojas de estilo y los scripts, y se conoce comúnmente como html.html.twig.

  • Contenedor de página: contiene el contenido generalmente encontrado entre las etiquetas body de un documento HTML, y se conoce como page.html.twig.

  • Encabezado: también se conoce como región y contiene generalmente el contenido del encabezado de nuestra página web. Esto puede ser parte de la plantilla page.html.twig o puede residir en una región especificada en nuestro archivo de configuración. Esto se conoce como region.html.twig.

  • Contenido: también se considera una región, y generalmente contiene nuestro contenido principal. Esto puede consistir en múltiples regiones subcontenidas, como nodos y comentarios. Los nodos y los comentarios tienen cada uno sus respectivas plantillas a las que se hace referencia como node.html.twig y comment.html.twig.

  • Barra lateral: también se considera una región. Esto puede contener bloques de contenido. Los bloques son creados por el administrador o por Drupal. El contenido dentro de estos bloques generalmente reside en block.html.twig.

  • Pie de página: esta es otra región que contiene contenido HTML, así como bloques de contenido.

Drupal y el motor de tema utilizado para convertir el marcado y las variables en HTML interpretan cada plantilla individual o serie de plantillas. Tenemos control total sobre lo que se genera utilizando el nuevo motor de plantillas Twig.

Una vez comencemos veremos un patrón de cómo se usan las plantillas, y a medida que ganemos experiencia, nos encontraremos usando cada vez menos plantillas.

Sin embargo, para empezar, crearemos ejemplos de cada uno para ayudar a aclarar su funcionalidad dentro de Drupal.

6.2. Donde encontrar plantillas

Lo bueno de Drupal es que, de manera predeterminada, el sistema central nos proporciona todas las plantillas que necesitamos usar. Por lo tanto, saber dónde encontrar las plantillas básicas es importante porque nos permitirá copiarlas en nuestra propia carpeta de temas para sobrescribirlas con nuestro propio marcado.

Comencemos por abrir nuestra instancia de Drupal en el explorador de archivos y naveguemos a la carpera core/modules. Dentro se encuentran los módulos principales que componen Drupal, junto con sus respectivas plantillas. La mayoría de las plantillas del núcleo se ubican en la carpeta core/modules/system/templates, como se muestra en la siguiente imagen:

Si buscamos los contenidos de la carpeta de plantillas veremos algunas de las plantillas más comunes que utilizaremos, incluidas las siguientes:

  • html.html.twig: contenedor HTML

  • page.html.twig: contenedor de página

  • region.html.twig: contenedor de región

Tres carpetas de plantillas más de las que debemos ser conscientes son:

  • core/modules/node/templates: contiene las plantillas para nodos.

  • core/modules/comment/templates: contiene las plantillas de comentarios.

  • core/modules/block/templates: contiene las plantillas para bloques.

Nos encontraremos reemplazando con frecuencia las plantillas, por lo que debemos asegurarnos de saber dónde encontrar cualquier plantilla de Twig que vayamos a tematizar.

La mayoría de nosotros hemos hecho algún desarrollo de PHP o al menos estamos los suficiente famiiliarizados con él para trabajar con las variables que produce Drupal. Entonces, cuando miramos las plantillas, deberíamos notar que los archivos no terminan con una extensión .php sino que terminan con una extensión .twig. De hecho, si tuviéramos que mirar la plantilla html.html.twig de la carpeta core/modules/system/templates, ni siquiera encontraríamos la sintaxis PHP dentro de ella:

<!DOCTYPE html>
<html{{ html_attributes }}>
<head>
<head-placeholder token="{{ placeholder_token|raw }}">
<title>{{ head_title|safe_join(' | ') }}</title>
<css-placeholder token="{{ placeholder_token|raw }}">
<js-placeholder token="{{ placeholder_token|raw }}">
</head>
<body{{ attributes }}>
<a href="#main-content" class="visually-hidden focusable">
{{ 'Skip to main content'|t }}
</a>
{{ page_top }}
{{ page }}
{{ page_bottom }}
<js-bottom-placeholder token="{{ placeholder_token|raw }}">
</body>
</html>

En cambio, veremos marcado HTML general junto con la sintaxis de Twig que generará contenido en su lugar. Echaremos un vistazo más de cerca a Twig en un momento. Primero, intentaremos crear un tema básico.