Templating

Conception de documents et d'interfaces numériques

On a deux problèmes actuellement :

 

  • La structure HTML de nos pages est dupliquée dans chaque fichier HTML
     
  • La structure des composants est dupliquée à chaque endroit où on les utilise

Ce serait bien de pouvoir définir la structure générale de la page, et dire que chaque page en "hérite", tout en ayant la possibilité de surcharger certains blocs...

Pug est un moteur de templates. Son but est de générer du code HTML.

Il utilise pour ça une syntaxe qui lui est propre.

<!DOCTYPE html>
<html lang="fr">
  <head>
  	<meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width,initial-scale=1"
    />
    <title>Hello world | My awesome site</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <h1 class="page-title">Hello world</h1>
    <p>This is my awesome website !</p>
    
    <div class="grid">
      <div>Item 1</div>
      <div>Item 2</div>
      <div>Item 3</div>
    </div>
  </body>
</html>
doctype html
html(lang="fr")
  head
    meta(charset="utf-8")
    meta(
      name="viewport",
      content="width=device-width,initial-scale=1"
    )
    title Hello world | My awesome site
    link(rel="stylesheet", href="style.css")

  body
    h1(class="page-title")
      | Hello world

    p
      | This is my awesome website!
      
    div(class="grid")
      - for (let i = 1; i <=3; ++i)
        div Item #{i}
doctype html
html
  head
    block head
      meta(charset="utf-8")
      title #{title} | My awesome website
      block stylesheets
        link(rel="stylesheet", href="style.css")

  body
    block body
extends base.pug

block prepend head
  - const title = "Home"

block body
  p  Hello, this is my home page!
extends base.pug

block prepend head
  - const title = "About"

block body
  p  This is the page about me, myself and I.
base.pug
index.pug
about.pug

Héritage

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>My awesome website</title>
  </head>
  <body>
 
  </body>
</html>

Héritage

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Home | My awesome website</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <p>Hello, this is my home page!</p>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>About | My awesome website</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <p>This is the page about me, myself and I.</p>
  </body>
</html>
index.html
about.html
  • La structure HTML de nos pages est dupliquée dans chaque fichier HTML
     
  • La structure des composants est dupliquée à chaque endroit où on les utilise
<div class="grid">
  <article class="item">
    <img src="..." alt="" class="item-image" />
    <h1>Item title 1</h1>
    <time>15/10/2020</time>
    <p>Item description</p>
  </article>
  <article class="item">
    <img src="..." alt="" class="item-image" />
    <h1>Item title 2</h1>
    <time>14/10/2020</time>
    <p>Item description</p>
  </article>
  <article class="item">
    <img src="..." alt="" class="item-image" />
    <h1>Item title 3</h1>
    <time>13/10/2020</time>
    <p>Item description</p>
  </article>
</div>

Disons qu'on a une structure comme celle-ci :

<article class="item">
  <img src="..." alt="" class="item-image" />
  <h1>Item title 1</h1>
  <time>15/10/2020</time>
  <p>Item description</p>
</article>

Qu'on réutilise plusieurs fois :

div(class="grid")
  article(class="item")
    img(src="...", alt="", class="item-image")
    h1 Item title 1
    time 15/10/2020
    p Item description 1
  article(class="item")
    img(src="...", alt="", class="item-image")
    h1 Item title 2
    time 14/10/2020
    p Item description 2
  article(class="item")
    img(src="...", alt="", class="item-image")
    h1 Item title 3
    time 13/10/2020
    p Item description 3

On peut traduire ça en Pug :

Mais le problème est toujours le même :

on répète plusieurs fois la même structure. Si un jour elle change, il faudra la changer partout à la main

div(class="grid")
  item(
    img="...",
    title="Item title 1",
    time="15/10/2020",
    description="Item description 1"
  )
  item(
    img="...",
    title="Item title 2",
    time="14/10/2020",
    description="Item description 2"
  )
  item(
    img="...",
    title="Item title 3",
    time="14/10/2020",
    description="Item description 3"
  )

Ce serait bien de pouvoir définir un nouvel élément et l'utiliser à plusieurs endroits :

mixin Item(props)
  article(class="item")
    img(src=props.img, alt=props.alt, class="item-image")
    h1=props.title
    time=props.date
    p=props.description
  
div(class="grid")
  Item({
    img: "...",
    alt: "",
    title: "Item title 1",
    date: "15/10/2020",
    description: "Item description 1"
  })
  Item({
    img: "...",
    alt: "",
    title: "Item title 2",
    date: "14/10/2020",
    description: "Item description 2"
  })
  Item({
    img: "...",
    alt: "",
    title: "Item title 3",
    date: "13/10/2020",
    description: "Item description 3"
  })

C'est possible grâce au système de "mixins" de Pug

mixin Item(props)
  article(class="item")
    img(
      src=props.img,
      alt=props.alt,
      class="item-image"
    )
    h1=props.title
    time=props.date
    p=props.description

Les mixins peuvent aussi être importées à partir d'un autre fichier :

components/Item.pug
include components/Item.pug

div(class="grid")
  +Item({
    img: "...",
    alt: "",
    title: "Item title 1",
    date: "15/10/2020",
    description: "Item description 1"
  })
  +Item({
    img: "...",
    alt: "",
    title: "Item title 2",
    date: "14/10/2020",
    description: "Item description 2"
  })
  +Item({
    img: "...",
    alt: "",
    title: "Item title 3",
    date: "13/10/2020",
    description: "Item description 3"
  })
page.pug

Parfois on a un composant qui ne fait qu'entourer d'autres composants :

Mais ça génère le HTML suivant :

<div class="wrapper">
  <article class="item">
    <!-- ... -->
  </article>
</div>
mixin Wrapper()
  div(class="wrapper")

mixin Item(props)
  article(class="item")
    // ...

+wrapper()
  +Item({ ... })

Si on traduit ça en Pug, on obtient le code suivant :

<div class="wrapper"></div>

Pour pouvoir faire de la composition de mixins, il faut utiliser un "block", pour indiquer à Pug qu'une mixin peut avoir des éléments enfants :

mixin Wrapper()
  div(class="wrapper")
    block

mixin Item(props)
  article(class="item")
    // ...

+wrapper()
  +Item({ ... })
<div class="wrapper">
  <article class="item">
    <!-- ... -->
  </article>
</div>

Liens complémentaires

Made with Slides.com