Comprendre le framework Z

, par _Eric_

Introduction

En premier lieu, il est nécessaire de lire ou de relire les articles sur SPIP-Contrib :

  • Le Squelette Zpip, qui reprend les concepts de base du framework dans sa version v1,
  • Différence entre Zcore et Zpip v1.x, qui explique la différence entre Zpip, le squelette Z de base qui utilise le framework Z v1 et Zcore le plugin fournissant les mécanismes du framework Z v2.
    et l’article Framework Z sur Nursit qui présente le framework Z dans sa version v2 utilisé par le squelette spipr-dist.

Les rappels qui sont faits dans cet article s’inspirent fortement de ces articles fondateurs mais sont reformulés ou précisés sous une forme différente qui me permet personnellement de mieux m’y retrouver.

Objectifs du framework Z

Le framework Z permet :

  • de séparer le layout du reste des squelettes et ainsi de limiter la duplication du code et de simplifier sa maintenance,
  • de proposer un mécanisme un thèmes incluant des CSS (et éventuellement un layout spécifique).
  • de faire varier la composition du contenu d’un type d’objet,

Ces mécanismes sont supportés par le plugin Zcore.

Organisation et génération d’une page HTML

Un page HTML se compose toujours de trois éléments de base, à savoir :

  • une balise <html> englobante précédée en général d’un doctype,
  • une balise <head> incluse contenant les meta, CSS et autres inclusions JS,
  • une balise <body> incluse contenant les éléments visibles de la page.

Le framework Z permet la construction de toute page HTML suivant ce modèle en imposant une organisation standard des éléments structurant de la page.

En premier lieu, Zcore embarque un fichier page.html à la racine qui est appelé sur chaque affichage d’une page. Ce fichier ne contient qu’une inclusion, celle du fichier structure.html auquel on passe les paramètres d’environnement, le type de page ${type-page} (ou sommaire par défaut) et éventuellement une composition.

C’est donc le fichier structure.html intégré à la racine de Zcore qui construit la page HTML de façon standard en incluant successivement dans la balise <html> - précédée d’un doctype - les éléments suivants :

  • un head propre à chaque page pour des CSS particulières par l’inclusion d’un fichier head/${type-page}.html
  • un head commun à toutes les pages par l’inclusion d’un fichier inclure/head.html
  • un head propre à chaque page pour des JS spécifiques par l’inclusion d’un fichier head_js/${type-page}.html
  • un layout unique par l’inclusion du fichier body.html

Le mécanisme Z de construction d’une page HTML impose donc une organisation physique du squelette Z en dossiers et fichiers. A ce stade, un squelette Z doit avoir l’organisation minimale suivante :

  • un body.html à la racine du squelette [1].
  • un dossier head/
  • un dossier head_js/
  • un dossier inclure/ avec un fichier head.html contenant les CSS et autres données communes incluses systématiquement dans le head de chaque page [2].

Layout unique, blocs Z et fichiers dist

Par défaut, le framework Z applique un layout unique à toutes les pages : le fichier body.html, colonne vertébrale d’un squelette Z. C’est lui qui va définir l’agencement et l’identité des blocs principaux de chaque page dans la balise <body>. Ci-dessous un exemple de body.html issu de Zpip-dist.

  1. <body>
  2. <div class="page">
  3. <div class="header" id="header">
  4. <INCLURE{fond=header/#ENV{type-page},env} />
  5. </div>
  6. <div class="nav hornav clearfix" id="nav">
  7. <INCLURE{fond=inclure/nav,env} />
  8. </div>
  9.  
  10. <div class="container">
  11. <div class="content" id="content">
  12. <INCLURE{fond=content/#ENV{type-page},env} />
  13. </div>
  14.  
  15. <div class="extra1 col" id="extra1">
  16. <INCLURE{fond=extra1/#ENV{type-page},env} />
  17. </div>
  18. <div class="extra2 col" id="extra2">
  19. <INCLURE{fond=extra2/#ENV{type-page},env} />
  20. </div>
  21. </div>
  22.  
  23. <div class="footer" id="footer">
  24. <INCLURE{fond=footer/#ENV{type-page},env} />
  25. </div>
  26. </div>
  27. </body>

Télécharger

On distingue dans cet exemple que le body peut contenir des blocs Z comme le header, le content ou le footer et des blocs “non Z” comme la barre de navigation d’id nav. Un bloc Z se reconnait par l’inclusion d’un squelette ${nom-bloc}/${type-page}.html à l’intérieur du bloc nommé défini en général par une balise <div>. Même si le nommage des blocs tend à se normaliser il est possible d’utiliser les noms que l’on souhaite. La liste des blocs Z est en outre définie dans une variable globale incluse dans le fichier d’options du squelette. Par exemple, pour Zpip-dist, le fichier d’options contient l’instruction suivante :

  1. if (!isset($GLOBALS['z_blocs']) OR !$GLOBALS['z_blocs'])
  2. $GLOBALS['z_blocs'] = array('content','extra1','extra2','head','head_js','header','footer');

Télécharger

Lors de l’affichage d’une page ${type-page}, Zcore essaye de trouver chacune des inclusions afin de calculer le contenu de la balise . Si on considère l’exemple de Zpip-dist dont le body contient 5 blocs Z et qu’on rajoute les deux head comme définis dans le chapitre précédent, une page est construite à partir de 7 inclusions spécifiques. C’est parfois un des reproche que l’on fait à Z, avis que je ne partage pas, car au contraire l’organisation a priori modulaire du framework Z permet de limiter l’écriture du code.

En outre, Zcore propose un mécanisme qui, si le fichier ${nom-bloc}/${type-page}.html n’existe pas recherche un fichier ${nom-bloc}/dist.html. Ces fichiers dist.html sont donc des squelettes communs réutilisables pour tout ou partie des pages du site ; c’est en particulier souvent le cas pour l’en-tête et le pied de page du site ainsi que dans une moindre mesure pour les blocs secondaires mais n’a pas de sens pour le corps de la page.
Par contre, Zcore renverra une erreur si aucun fichier ni ${nom-bloc}/${type-page}.html ni dist.html n’est trouvé. Il est donc nécessaire de créer des fichiers dist.html pour chaque bloc sauf le corps y compris les deux head même si ceux-ci sont vides.

A ce stade, on peut compléter l’organisation minimale d’un squelette Z :

  • un body.html à la racine du squelette qui définit la liste des blocs Z ;
  • un dossier head/ avec à minima un fichier dist.html vide (sinon on utilise celui fourni par Zcore) ;
  • un dossier head_js/ avec à minima un fichier dist.html vide (sinon on utilise celui fourni par Zcore) ;
  • un dossier inclure/ avec un fichier head.html ;
  • un dossier par bloc Z sauf le corps avec à minima un fichier dist.html vide
  • un dossier pour le bloc Z du corps avec à minima un fichier sommaire.html pour la page d’accueil.

Retour sur le head

La balise <head> est un élément structurel (au même titre que les tags ou ) d’un document html. Elle contient les informations essentielles à la description du document qui sera affiché dans le corps de la page, à savoir :

  • le titre du document (inclus dans la balise <title>)
  • les références aux feuilles de style utilisées par le document
  • les références aux javascripts utilisés par le document
  • les balises <meta> pouvant spécifier l’auteur, la description du contenu, l’encodage et de nombreuses autres meta-données.

Certaines de ces informations sont communes à toutes les pages et d’autres spécifiques à une page donnée. Le framework Z propose une structuration des informations communes et spécifiques en imposant trois niveaux de head appelés successivement par le fichier structure.html, à savoir, head/${type-page}.html, inclure/head.html et head_js/${type-page}.html.

Le fichier head/${type-page}.html

Ce fichier est appelé spécifiquement pour une page donnée ${type-page}. Par défaut, si le fichier spécifique à la page n’existe pas Zcore se rabat sur le fichier head/dist.html.

Classiquement ce head permet d’insérer avant les données communes aux pages des informations spécifiques comme le titre de la page, la description de l’article pour une page article et parfois des CSS spécifiques. Cette inclusion est une sorte de pre-head.

L’environnement est passé à ce fichier.

Le fichier inclure/head.html

Ce fichier est appelé systématiquement par Zcore à chaque construction d’une page. Il est censé contenir les inclusions communes à toutes les pages. On y retrouve donc classiquement :

  • les meta permettant de déclarer le « generator » et le charset du site ;
  • le lien vers le flux RSS si disponible ;
  • les CSS communes classées dans un ordre précis que l’on discutera plus avant dans cet article ;
  • les balises #INSERT_HEAD_CSS et #INSERT_HEAD pour autoriser l’insertion de CSS ou de JS par les plugins tiers ;
  • les éventuelles feuilles de styles nécessaires aux thèmes voire à une personnalisation propre ;
  • le favicon.

Cette liste n’est pas exhaustive mais est représentative du contenu de ce fichier. L’ordre dans lequel sont faits positionnées les instructions est bien entendu primordial. Pour Zpip-dist, le contenu du fichier est le suivant :

  1. [(#REM)
  2. Head standard de toutes les pages ; les elements specifiques
  3. (title, description) figurent dans le squelette article.html
  4. ]
  5. [(#REM) Preciser le charset ]
  6. <meta http-equiv="Content-Type" content="text/html; charset=#CHARSET" />
  7.  
  8. [(#REM) Fierement fabrique avec SPIP ]
  9. <meta name="generator" content="SPIP[ (#SPIP_VERSION)]" />
  10.  
  11. [(#REM) Lien vers le flux RSS du site ]
  12. [<link rel="alternate" type="application/rss+xml" title="<:syndiquer_site:>" href="(#URL_PAGE{backend})" />]
  13.  
  14. [<link rel="stylesheet" href="(#CSS{css/reset.css})" type="text/css" />]
  15. [<link rel="stylesheet" href="(#CSS{css/font.css})" type="text/css" />]
  16. [<link rel="stylesheet" href="(#CSS{css/typo.css})" type="text/css" />]
  17. [<link rel="stylesheet" href="(#CSS{css/box.css})" type="text/css" />]
  18. [<link rel="stylesheet" href="(#CSS{css/box_skins.css})" type="text/css" />]
  19. [<link rel="stylesheet" href="(#CSS{css/form.css})" type="text/css" />]
  20.  
  21. [(#REM) Balise permettant aux plugins d'inserer des fichiers CSS ]
  22. #INSERT_HEAD_CSS
  23.  
  24. [<link rel="stylesheet" href="(#CSS{css/spip.css})" type="text/css" />]
  25. [<link rel="stylesheet" href="(#CSS{css/spip.form.css})" type="text/css" />]
  26. [<link rel="stylesheet" href="(#CSS{css/spip.comment.css})" type="text/css" />]
  27. [<link rel="stylesheet" href="(#CSS{css/spip.list.css})" type="text/css" />]
  28. [<link rel="stylesheet" href="(#CSS{css/spip.petition.css})" type="text/css" />]
  29. [<link rel="stylesheet" href="(#CSS{css/spip.pagination.css})" type="text/css" />]
  30. [<link rel="stylesheet" href="(#CSS{css/spip.portfolio.css})" type="text/css" />]
  31. [<link rel="stylesheet" href="(#CSS{css/clear.css})" type="text/css" />]
  32. [<link rel="stylesheet" href="(#CSS{css/grid.css})" type="text/css" />]
  33. [<link rel="stylesheet" href="(#CSS{css/button.css})" type="text/css" />]
  34. [<link rel="stylesheet" href="(#CSS{css/layout.css})" type="text/css" />]
  35.  
  36. [(#REM) Feuille de style du theme ]
  37. [<link rel="stylesheet" href="(#CSS{css/theme.css})" type="text/css" />]
  38.  
  39. [(#REM) Feuille de style CSS pour l'impression, n'existe pas par defaut ]
  40. [<link rel="stylesheet" href="(#CSS{css/print.css})" type="text/css" media="print" />]
  41.  
  42. [(#CHEMIN{inc-theme-head.html}|oui)
  43. #INCLURE{fond=inc-theme-head,env}
  44. ]
  45.  
  46. [(#REM) Feuille de style personnalisee pour surcharger les precedentes
  47. A noter par defaut cette css n'existe pas
  48. ]
  49. [<link rel="stylesheet" href="(#CSS{css/perso.css})" type="text/css" />]
  50.  
  51. [(#REM) Balise permettant aux plugins d'inserer des appels javascript ou css ;
  52. C'est ici que SPIP va inserer l'appel de la librairie jQuery
  53. Et appeler a la fin compacte_head pour agreger et compacter tout le head dans des fichiers statiques
  54. si l'option est cochee dans Configuration
  55. ]
  56. #INSERT_HEAD
  57.  
  58. [<link rel="icon" type="image/x-icon" href="(#CHEMIN{favicon.ico})" />
  59. [<link rel="shortcut icon" type="image/x-icon" href="(#CHEMIN{favicon.ico})" />]]

Télécharger

Il faut noter que l’environnement n’est pas fourni à ce fichier de head pour des raisons de performance, il n’est donc pas possible d’y introduire une personnalisation liée à une variable d’environnement ; il faut passer par une configuration ou le faire dans les autres fichiers de head.

Le fichier head_js/${type-page}.html

Ce fichier est lui aussi appelé spécifiquement pour une page donnée ${type-page}. Par défaut, si le fichier spécifique à la page n’existe pas Zcore se rabat sur le fichier head/dist.html.

Classiquement ce head permet d’insérer après les données communes aux pages des informations spécifiques, en particulier les scripts JS. Cette inclusion est une sorte de post-head.

L’environnement est passé à ce fichier.

Pages automatiques et échafaudage

A compléter.

Thèmes

A compléter.

Notes

[1Zcore embarque aussi un fichier body.html très rudimentaire. Il convient toujours de le redéfinir pour les besoins du squelette.

[2Zcore embarque aussi un fichier inclure/head.html plutôt destiné à Zpip-dist. Il est donc presque toujours nécessaire de le redéfinir pour les besoins du squelette.