Modèle de squelette réutilisable

Vers un modèle de squelette pour favoriser la réutilisation, le partage et l’accroissement collectif de la connaissance, suite des réflexions de « L’après SPIP 2.0 ».

La dist de SPIP 1.9.x et 2.0

La dist de SPIP se veut simple à appréhender par un squelette unique pour chaque objet (article, rubrique, etc.), assurant chacun la présentation des informations de cet objet.

Ainsi tous les articles sont affichés via article.html, toutes les rubriques via rubrique.html, et ainsi de suite.

Il est facile de trouver quel squelette affiche une information, de le copier dans le dossier squelettes/ pour le modifier et le personnaliser ensuite (modifier le contenu de la colonne de navigation, l’ordre d’affichage des sous rubriques …).

Mais cette pratique, encouragée par la documentation de SPIP et la mise à disposition de ce modèle par défaut dans SPIP, conduit dans les faits à de bien mauvaises pratiques qui ont leurs effets pervers néfastes.

Une duplication sans fin du code

La première mauvaise pratique est la duplication pure est simple d’un même code. Ainsi, pour modifier parfois juste un détail (disons l’ordre d’affichage des rubriques dans le menu de navigation), on se retrouve obligé de dupliquer tout le squelette de la page dans laquelle se trouve le menu.

La duplication du code n’est pas une difficulté technique en soi, tout le monde, ou presque, manipulant avec aisance le copier-coller. C’est juste contre-productif en terme de maintenance.

Lorsque après avoir dupliqué le même code à de nombreuses reprises, vous lirez à l’occasion d’une mise à jour de SPIP qu’une boucle de la dist aura été corrigée, que vous restera-t-il à faire ? Juste à rééditer toutes vos copies, et les corriger. Perte de temps et de qualité (une opération manuelle réalisée N fois étant statistiquement sujette à erreur).

Peu de partage de code possible
L’organisation et le schéma des squelettes de la dist montrant l’exemple, chacun ajoute directement des fonctionnalités supplémentaires dans ses squelettes personnalisés. Oh, certes, chacun évite de réinventer la roue, et n’hésite pas à copier-coller telle boucle vue sur SPIP-contrib, telle autre déjà codée sur un autre projet, ou encore telle autre récupérée en lisant le squelette d’un site en ligne.

Mais ce n’est jamais le même composant que l’on réutilise. Juste une copie d’un composant déjà fait quelque part. Et si quelqu’un l’améliore à la faveur d’un site, personne n’en profitera.

Chacun refait la même chose dans son coin
Du coup, chacun refait la même chose dans son coin. Et plusieurs fois, même. Correction de bug, modification fonctionnelle, ajouts etc …

Simplement parce que l’architecture initiale proposée par SPIP n’est pas adaptée à une réutilisation maximale, et continue à être malgré tout propagée par imitation.

Chaque montée de version est un cas unique
Chaque site ayant ses propres squelettes, il doit être traité comme un cas unique isolé lors des montées de version. Avec comme conséquence de nombreux sites qui ne sont pas mis à jour.

Un nouveau modèle

Avec SPIP 2.0 sont arrivés un certain nombre d’outils qui permettent d’ouvrir une nouvelle voie que nous allons essayer d’esquisser ici.

Séparer le layout du reste des squelettes
Le « layout » c’est la structure générale de votre page HTML, les grands blocs qui la forment. Un layout simpliste pourrait être :

<div id=’entete’>  </div>

<div id=’contenu’>

</div>

</div id=’navigation’>

</div>

<div id=’pied’> </div>

Un même layout peut avoir plusieurs habillages. Mais aucun layout ne peut prétendre la généricité complète. Il faut donc pouvoir changer l’organisation structurelle du site. Mais si l’on garde en tête les défauts de la méthode copier-coller, il faut donc que cela n’entraîne aucune autre duplication de code.

Dans la dist, l’organisation de la page est écrite dans chaque squelette. Changer cette organisation entraîne donc la duplication ipso-facto de tous les squelettes de la dist. Ce que l’on veut éviter.

On propose donc que le layout de la page soit défini à un seul endroit, un squelette nommé body.html, qui détermine le body et son contenu, et appellera une inclusion pour chaque bloc structurel.

Voici un exemple de body.html pour page structurée comme la dist de SPIP :

<body class="page_#ENV{type}">

	<div id="page">
		[(#REM) Entete de la page + titre du site ]
		<div id='bloc-haut'>
			<div id="entete">
				<INCLURE{fond=inc/entete}{id_rubrique}>
			</div>
                  	<INCLURE{fond=inc/barre-nav}{id_rubrique}>
            	</div>

		<div id='bloc-central'>
			[(#REM) Contenu principal : contenu de l'article ]

			<div class="hfeed" id="conteneur">
				<div class="hentry" id="contenu">
					[(#REM) Appeler le fond contenu/article si un modele est passe en declinant pour chaque type ]
                          		<INCLURE{fond=contenu/#ENV{type}}{env}>
				</div><!--#contenu-->
			</div><!--#conteneur-->

			[(#REM) Menu de navigation laterale ]
			<div id="navigation">
				<INCLURE{fond=navigation/#ENV{type}}{env}>
          		</div><!--#navigation-->

	          	[(#REM) Menu de navigation laterale ]
        	  	<div id="extra">
				<INCLURE{fond=extra/#ENV{type}}{env}>
			</div><!--#extra-->
			<div class='nettoyeur'></div>
		</div><!-- #bloc-central-->

		[(#REM) Pied de page ]
		<div id="bloc-bas">
			<div id="pied">
				<INCLURE{fond=inc/pied}>
			</div>
		</div>
	</div><!--#page-->
</body> 

Cette proposition amène plusieurs commentaires :

  • On propose d’avoir 3 blocs fonctionnels communs : l’en-tête, le pied, et la barre de navigation. Les autres blocs sont à chaque fois liés au type de l’objet affiché
  • En ce qui concerne l’organisation de ces autres blocs, on propose d’adopter une organisation des répertoires similaire à celle de la page, en répartissant les morceaux de chaque type dans des sous dossiers portant le même nom que les blocs. Ainsi pour la page article.html on aurait :
    • contenu/article.html
    • navigation/article.html
    • extra/article.html
  • Enfin, le squelette principal se trouve extrêmement simplifié
    Pour une page article nous aurions par exemple pour article.html :
     <BOUCLE_article_principal(ARTICLES) {id_article}>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="#LANG" lang="#LANG" dir="#LANG_DIR">
    
    <head>
    
    <title>[(#TITRE|textebrut) - ][(#NOM_SITE_SPIP|textebrut)]</title>[
    
    <meta name="description" content="(#INTRODUCTION{150}|attribut_html)" />
    
    ]<B_URLMOT>
    
    <link rel="alternate" type="application/rss+xml" title="<:titre_page_mots_tous:>" href="#URL_PAGE{backend}<BOUCLE_URLMOT(MOTS){id_article}>&amp;id_mot[]=#ID_MOT</BOUCLE_URLMOT>" />
    
    </B_URLMOT><B_URLAUTEURS>
    
    <link rel="alternate" type="application/rss+xml" title="<:icone_auteurs:>" href="#URL_PAGE{backend}<BOUCLE_URLAUTEURS(AUTEURS){id_article}>&amp;id_auteur[]=#ID_AUTEUR</BOUCLE_URLAUTEURS>" />
    
    </B_URLAUTEURS><INCLURE{fond=inc/head}>
    
    </head>
    
          <INCLURE{fond=body}{env}{type=article}{id_rubrique}>
    
    </html>
    
    </BOUCLE_article_principal>

On voit déjà que ce début d’organisation permet de modifier indépendamment le layout, le contenu affiché et les colonnes navigation et extra pour chaque type d’objet.

Faire varier la composition du contenu d’un type d’objet

On peut souhaiter que le contenu s’affiche différemment, avec un fonctionnement différent, selon les cas. Exemple typique : telle rubrique listera tous ses contenus, alors que telle autre n’afficherait qu’un texte d’accueil, les sous-rubriques étant alors accessibles par son menu de navigation latéral. Peut-on trouver une réponse simple à ce besoin ?

Les solutions à base de mots-clés ou de squelette rubrique-XX.html sont en pratique désastreuses dès lors qu’elles sont mises entre les mains de tierces personnes n’ayant pas participé à la conception du site.

Le plugin Compositions améliore cela. Il permet de faire varier la composition, objet par objet. Le squelette peut contenir lui-même plusieurs variantes, mais les plugins peuvent aussi proposer des compositions prêtes à l’emploi. Par exemple, le plugin agenda pourrait proposer une composition contenu/rubrique-agenda.html pour présenter le contenu d’une rubrique agenda, laquelle serait ainsi réutilisable sur tous les sites bâtis sur ce même modèle de squelettes.

Ce mécanisme permet donc de partager des compositions d’objet, ou de diffuser des compositions d’objet via les plugins, pour leur réutilisation.

Thèmes

Le modèle de squelettes dont il est question ici, permet aussi de définir un mécanisme de thèmes comportant :

  • une ou plusieurs feuille de style CSS
  • un dossier d’images décoratives
  • un body éventuellement, pour définir un layout spécifique au thème.

Un ensemble de conventions de nommage des sélecteurs CSS doit être proposé pour permettre aux thèmes de fonctionner de la même façon sur tous les squelettes qui s’organisent selon le modèle décrit ici.

Un sélecteur de thèmes
Le thème peut être déposé dans le dossier themes/ à la racine de SPIP, et sera alors géré uniquement par un sélecteur de thèmes, ou déposé dans le dossier plugins/ et activé simplement via le gestionnaire de plugins.

Les thèmes ont tous le même prefix pour permettre de n’en activer qu’un à la fois via le gestionnaire de plugins. Ce préfixe sera aussi celui du gestionnaire de thèmes, ce qui interdira l’utilisation de ce gestionnaire ET l’activation d’un plugin thème par le gestionnaire de plugins.

En route !

Une grande partie de la généricité des mécanismes proposés repose sur la possibilité d’inclure avec {env}, c’est-à-dire sans connaissances des paramètres à passer. Cette amélioration a été apportée par SPIP 2, et en cela, il n’était pas possible d’arriver à ce résultat avant.

Cette proposition de fonctionnement devrait permettre de partager des blocs de squelette, distribuables de façon centralisée, ainsi que les compositions.

Rendre ce partage possible conduirait probablement à mieux mutualiser les efforts et pourrait permettre de simplifier la maintenance et l’évolution des sites.

En permettant la mise en place d’un système de thèmes, c’est aussi un manque que l’on espère combler par cette proposition.

Le squelette Zpip est la mise en application de ce modèle.

Discussion

5 discussions

  • bruno poterie

    bonjour,
    j’essaye de créer en partie publique (via le plugin « menus ») un lien vers la page des sites référencés. Normalement, vu le fichier site.html, ce devrait être :

    (http://monsite)/spip.php ?page=site

    hélas, je reçois une erreur 404

    Ai-je oublié quelque chose ?

    Répondre à ce message

  • Bonjour,

    Je travaille sur un squelette suivant ce modèle, en prenant Zspip pour point de départ.

    J’ai deux boucles articles dans #contenu et dans #extra avec le critère doublons mais SPIP a l’air de s’en moquer (oui dans TMA, les derniers articles sont dans #extra).

    J’imagine que c’est parce que chaque inclure hérite de l’environnement de body-layout mais est calculé de manière indépendante des autres.

    Existe-t-il un moyen de faire passer une information d’un inclure à l’autre dans ce schémas de développement ? En l’espèce le fameux doublons mais j’imagine que le problème peut se poser dans d’autres cas.

    J’utilise pour l’instant une solution quick&dirty qui est simplement de reproduire dans l’#extra la même boucle que dans #contenu sans rien afficher.

    Répondre à ce message

  • 1

    Je viens également de regarder à nouveau la vidéo d’Avignon dans laquelle Mathieu et toi abordiez cette question de réorganiser les squelettes pour pouvoir plus efficacement mettre en place une gestion de « thèmes »...
    Vous y disiez tous les deux qu’il restait à adopter une convention commune histoire de pouvoir plus facilement établir des ponts, de faciliter les échanges. Faut-il comprendre que la contrib que tu viens de mettre en ligne est le prolongement de ce travail commun ?

    • Tout à fait, et elle amorce une série de contributions sur ce point. La suite arrive très vite !

    Répondre à ce message

  • Merci Cedric pour cette contribution

    Répondre à ce message

  • La suite ! La suite ! La suite !

    Merci pour cette intéressante contribution.

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom