Cyrille Perois
Front-end architect @ w3r.one
Conception de documents et d'interfaces numériques
On a deux problèmes actuellement :
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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>My awesome website</title>
</head>
<body>
</body>
</html>
<!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
<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>
By Cyrille Perois