#DrupalCampSpain2015 @pakmanlh

Theming in Drupal 8

«un soplo de aire fresco»

¿Quien soy? ¿De dónde vengo?

Pako Garcia

Vegan Frontend developer at
@pakmanlh in the internets

¿A todos nos gustan los ponies?

Recomendaciones del chef:

  • 10:30 to 11:30
    Render API en Drupal 7 & 8
    Jose Luis Bellido
  • 12:00 to 13:00
    Drupal 8 Frontend for Backenders
    Lauri Eskola

Cualquier tiempo pasado fue mejor

¿seguro?

Divitis

Marcado enriquecido tm


Hola! soy el marcado de Drupal

Otro div más, porque no...

sobrecarga css

27 archivos css en Stark de Drupal 7






					    

sobrecarga css

5 classes para cada uno de los campos


El valor relevante

Uso masivo de phptemplate

más de 5000 líneas de PHP en plantillas sin despeinarnos.

y demás lindezas

  • Theme functions
  • Difícil comprensión para no-expertos
  • Poco interés por el CSS
  • ...

pero...

drupal 8 está aquí!

...o casi.

Cambios en la capa de theme

Template process layer

…es historia!

Theme functions

…están siendo convertidas a plantillas…
(y en otros formatos).

Solamente quedan 12! http://dgo.to/2348381

Adiós theme(), hola
render arrays

Drupal 7:

          $variables['list'] = theme('item_list', array(
            'items' => $items,
          ));
          
Drupal 8:

          $variables['list'] = [
            '#theme' => 'item_list',
            '#items' => $items,
          ];
          

Theme suggestion hooks

Drupal 7:

/**
 * Implements hook_preprocess_HOOK() for node templates.
 */
function MYTHEME_preprocess_node(&$variables) {
  $variables['theme_hook_suggestions'][] = 'node__' . 'my_first_suggestion';
  $variables['theme_hook_suggestions'][] = 'node__' . 'my_second_more_specific_suggestion';
}
Drupal 8:

/**
 * Implements hook_theme_suggestions_HOOK_alter() for node templates.
 */
function MYTHEME_theme_suggestions_node_alter(array &$suggestions, array $variables) {
  $suggestions[] = 'node__' . 'my_first_suggestion';
  $suggestions[] = 'node__' . 'my_second_suggestion';
}

Atributos

Todos los atributos de la etiqueta:
<div{{ attributes }}>
Cuidado con el primer espacio en blanco:
<div {{ attributes }}>
Este espacio se sumará quedando un código feo
<div✖{{ attributes }}>

Atributos II

Dividiendo el atributo class
<div class="myclass {{ attributes.class }}"{{ attributes|without('class') }}>

Atributos III

Manipulación de Class:
<div{{ attributes.addClass('hola').removeClass('adiós') }}>
Testing:
{% if attributes.hasClass('field-label-inline') %}
  {# Realizar algún código personalizado para la etiqueta inline. #}
{% endif %}

Atributos IV

Establecer un atributo:
<div{{ attributes.setAttribute('id', 'eye-d') }}>
Borrar un atributo:
<div{{ attributes.removeAttribute('id') }}>

Imprime lo que quieras, cuando quieras

Drupal 7:


// Ocultamos los comentarios y los links
// para imprimirlos después.
hide($content['comments']);
hide($content['links']);
print render($content);
// Render llama a show() en el elemento.
print render($content['links']);
// Para devolver los enlaces con el contenido.
show($content['links']);
// Imprime el contenido con enlaces pero todavía
// sin comentarios :(
print render($content);

Drupal 8:

{# Imprime el contenido sin comentarios ni enlaces #}
{{ content|without('comments', 'links') }}

{# Imprime solamente los enlaces #}
{{ content.links }}

{# Imprime todo sin los comentarios! #}
{{ content|without('comments') }}

{# Imprime todo YUJU :) #}
{{ content }}

Uy sí, y Twig!

Creo que lo habréis notado… 😉

services.yml:
parameters:
  twig.config:
    debug: true
Ejemplo de código:

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
   * block--bartik-powered.html.twig
   * block--system-powered-by-block.html.twig
   * block--system.html.twig
   x block.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/block/templates/block.html.twig' -->
<div class="block block-system contextual-region" id="block-bartik-powered" role="complementary">
  <div data-contextual-id="block:block=bartik_powered:"></div>
  <div class="content">
    <span>Powered by <a href="http://drupal.org">Drupal</a></span>
  </div>
</div>
<!-- END OUTPUT from 'core/modules/block/templates/block.html.twig' -->

Drupal 7.33+ también!!

settings.php:
$conf['theme_debug'] = TRUE;
Example output:

<!-- THEME DEBUG -->
<!-- CALL: theme('block') -->
<!-- FILE NAME SUGGESTIONS:
   * block--system--powered-by.tpl.php
   * block--system.tpl.php
   * block--footer.tpl.php
   x block.tpl.php
-->
<!-- BEGIN OUTPUT from 'modules/block/block.tpl.php' -->
<div id="block-system-powered-by" class="block block-system">
  <div class="content">
    <span>Powered by <a href="https://www.drupal.org">Drupal</a></span>
  </div>
</div>
<!-- END OUTPUT from 'modules/block/block.tpl.php' -->

Twig magic


// Valor de un Array.
$bocadillo['tofu'];
// Propiedad de un objeto.
$bocadillo->tofu;
// También para el método mágico.
$bocadillo->__isset('tofu'); && $bocadillo->__get('tofu');
// Para un método de un objeto.
$bocadillo->tofu();
// Para un objeto obtenido con la convención get.
$bocadillo->getTofu();
// Objeto is convención método.
$bocadillo->isTofu();
// Método dinámico.
$bocadillo->__call('tofu');

{{ bocadillo.tofu }}

Autoescape


              $user->field_first_name = "<script>alert('XSS')</script>";
Drupal 7:
MAL   <?php print $user->field_first_name; ?>
BIEN  <?php print check_plain($user->field_first_name); ?>
Drupal 8:
BIEN {{ user.field_first_name }}
MAL  {{ user.field_first_name|raw }}

Extender «bloques» con Twig

Definimos una «zona variante»
page.html.twig


{% block variante %}
{% endblock %}

Extender «bloques» con Twig

Heredamos toda la página,
modificando solamente ese trozo

page--front.html.twig


{% extends "page.html.twig" %}
{% block variante %}

Contenido específico de la página principal.

{% endblock %}

Modificar marcado del menu

Usando una macro recursivo de Twig en menu.html.twig

Ejemplo!

Modificar marcado del paginador

Modificando pager.html.twig

Ejemplo!

Classy

un nuevo base theme amigo

Drupal 7

Theme Stark

HTML + class="foo"

Drupal 8

Theme Stark + Classy

HTML + class="foo"

¿Nuestro theme?

Usando solamente Core

{{{ code }}

Con Classy como Basetheme

{{{ code }}

Classy

Organización por tipos de plantillas

Definir Classy como Basetheme

*.info.yml
base theme: classy

Configurando un Theme

¿Dónde viven ahora?

[root]/themes/[theme_name]

Archivos de configuración

  • [our_theme].info.yml
  • [our_theme].libraries.yml
  • [our_theme].breakpoints.yml
  • [our_theme].theme.yml

Ejemplo!

Mejoras en CSS

Nueva arquitectura CSS (1887918)


.notification {
  /* Estilos generales para todas las notificaciones. */
}
.notification--info {
  /* Ajustes de color concretos. */
}				        		

Mejoras en CSS

Nueva arquitectura CSS (1887918)


/* Componente botón */
.button {
  /* estilos */
}
/* Clase modificadora del botón */
.button--primary {
  /* Modificadores y añadidos. */
}				        		



Mejoras en CSS

CSSLint como arma (1190252)

Herramienta para mejorar la calidad del código.

https://github.com/CSSLint/csslint/wiki

Drupal Core Frontend toolkit

Status

Gracias!

That's all folks

¿Preguntas?

pako@ymbra.com
@pakmanlh