2.0.3
PugPug(パグ)は HTML を効率的に書ける Node.js + JavaScript 製のテンプレートエンジンです。元は Jade(ジェード)という名前でしたが、商標の関係で改名されました。繰り返しや属性などの書き方が変更されているので、Jade 時代のコードを流用する場合はシンタックスエラーに注意しましょう。
単一ファイルの拡張子は .pug
となりますが、そのままではブラウザで解釈できません。Web として表示させるには HTML へとコンパイルする必要があります。
Example
Pug は Ruby のようにインデントで階層化を行い書いていく記法を基本としており、コンパイルすることで HTML が出力できます。閉じタグは不要。JavaScript のように変数・繰り返し・条件分岐も書けます。また、Pug ファイルは分割して複数ページで使い回せます。
doctype html
html(lang="ja")
head
meta(charset="UTF-8")
title タイトル
body
main#main
ul.btns
li
a.btn(href="/") ボタン
↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
</head>
<body>
<main id="main">
<ul class="btns">
<li><a href="/" class="btn">ボタン</a></li>
</ul>
</main>
</body>
</html>
Compile
Pug を HTML にコンパイルして Web で表示させる方法は大きく分けて 3 種類あります。
Basic Compile
Pug のコンパイルとしてはもっとも簡単な手法。コンパイラーアプリや CLI ツールで Pug ファイルを監視、随時 HTML を生成しサーバーに上げます。アプリは Win/Mac 対応シェアウェアの Prepros、CLI ツールは gulp が多く使われています。
10 ページ程度の静的な Web サイトを制作する際には効率的ですが、20 ページを超える頃にはコンパイルにかかる時間がストレスになります。ディレクトリ分割か監視対象のカスタマイズを検討しましょう。
Temporary Compile
Node.js が動くローカルサーバーで一時的に Pug をコンパイルしながら開発する手法。webpack Serve(旧 webpack-dev-server)で pug-loader
などを使って随時 HTML を返します。Vue や React テンプレートの HTML 部分を Pug で書く場合もこの手法に当たります。
開発環境がホットリロードに対応しているため、ファイル数が増えてもストレスがありません。時間がかかる作業は最終的なビルドのみです。
Server Compile
Node.js が動くサーバーに Express などを導入して Pug ファイルを動かす手法。ページにアクセスがあった際、動的に Pug を HTML に変換して表示させます。
Decompile
既存の HTML を Pug にしたい場合は逆コンパイルを行う必要があります。一番手軽なのは、Web 版の HTML2Jade(Pug)で変換することです。
Comment
Pug のコメントは //
だと HTML に出力、//-
と書くことで出力されないコメントにできます。
// 出力されるコメント
//- 出力されないコメント
↓
<!-- 出力されるコメント-->
Include
Basic Include
include
でパスを書くことで分割した Pug ファイルを読み込めます。
include section/_header.pug
main#main
ul.btns
li
a.btn(href="/") ボタン
include section/_footer.pug
↓
<header>
<h1>
<a href="#"><img src="img/logo.svg" alt="Pugの説明ページ|Pugの説明サイト" class="logo"></a>
</h1>
</header>
<main id="main">
<ul class="btns">
<li><a href="/" class="btn">ボタン</a></li>
</ul>
</main>
<footer>
<p class="copylight">© 運営会社名</p>
</footer>
Root Include (gulp)
gulp で複数ページを制作している際、include
をルートパスにしたいと考えるでしょう。その場合は、gulpfile.js
内にオプションで basedir
を設定します。
project
├── gulpfile.js
├── docs
│ └── index.html
└── src
└── pug
├── index.pug
└── section
├── _footer.pug
├── _header.pug
└── _main.pug
//- index.pug
include /section/_header.pug
include /section/_main.pug
include /section/_footer.pug
// gulpfile.js
const gulp = require("gulp")
const pug = require("gulp-pug")
const paths = {
src_pug: "src/pug/",
out_html: "docs/"
}
const pugOptions = {
basedir: src_pug
}
gulp.task("pug", () => {
return gulp
.src([paths.src_pug + "**/*.pug", "!" + paths.src_pug + "**/_*.pug"])
.pipe(pug(pugOptions))
.pipe(gulp.dest(paths.out_html))
})
Variable
- var
で変数を宣言して Pug 内で使い回せます。
- var title = "Pugの説明ページ|色々と説明するサイト";
doctype html
html(lang="ja")
head
meta(charset="UTF-8")
title #{title}
body
header
h1
a(href="#")
img.logo(src="img/logo.svg" alt=title)
↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Pugの説明ページ|色々と説明するサイト</title>
</head>
<body>
<header>
<h1>
<a href="#"><img src="img/logo.svg" alt="Pugの説明ページ|色々と説明するサイト" class="logo"></a>
</h1>
</header>
</body>
</html>
変数は JSON 形式で入れ子にできます。そのため、複数ページ・複数コンテンツのメタデータを 1 箇所にまとめておき、必要に応じて引き出す管理方法を取れます。
//- base/_config.pug
-
var pages = {
index: {
id: "index",
title: "QRANOKO",
desc: "CREATIVE PARTNERS",
class: [ "qranoko", "qranoko-index" ],
url: "index.html",
ogp: "ogp.png",
agent: "rwd",
login: "no"
},
about: {
id: "about",
title: "ABOUT - QRANOKO",
desc: "CREATIVE PARTNERS",
class: [ "qranoko", "qranoko-about" ],
url: "about.html",
ogp: "ogp.png",
agent: "rwd",
login: "no"
}
//- about.pug
include /base/_config.pug
- var key = "about"
- var page = pages[key]
h1= page.title
↓
<h1>ABOUT - QRANOKO</h1>
Case
変数で条件分岐させる際に case
が使えます。when
で値を指定。default
はすべて当てはまらないときに実行されます。
- var page = "index";
case page
when "index"
h1 タイトル
when "guide"
h1 ページ|タイトル
default
p タイトル
↓
<h1>タイトル</h1>
if else
変数で条件分岐させる際に if
が使えます。if
で変数に値が入っている場合だけ出力・特定の値の場合だけ出力、else
で合致しない場合の出力を書けます。
- var item_01 = "ペンシル";
- var item_02 = "";
- var item_03 = "消しゴム";
if item_01
p= item_01
if item_02
p= item_02
if item_03 === "鉛筆"
p えんぴつ
else if item_03 === "筆箱"
p ふでばこ
else
p なし
↓
<p>ペンシル</p>
<p>なし</p>
each
each
で繰り返しの出力ができます。画像のパスとタイトルだけ変えて繰り返す場合などによく使います。
ul
each val in [1, 2, 3, 4, 5]
li= val
↓
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
入れ子の変数を用いることで柔軟な制作が可能になります。
-
var nav = {
index : {
title : "HOME",
url : "/"
},
about : {
title : "ABOUT",
url : "about.html"
},
works : {
title : "WORKS",
url : "works.html"
},
/*service : {
title : "SERVICE",
url : "service.html"
},*/
contact : {
title : "CONTACT",
url : "contact.html"
}
}
nav.nav.is-global
each val in nav
a.nav-item(href=val.url)
span.text= val.title
↓
<nav class="nav is-global">
<a class="nav-item" href="/"><span class="text">HOME</span></a>
<a class="nav-item" href="about.html"><span class="text">ABOUT</span></a>
<a class="nav-item" href="works.html"><span class="text">WORKS</span></a>
<a class="nav-item" href="contact.html"><span class="text">CONTACT</span></a>
</nav>
while
while
を使うことで回数を決めて繰り返すことができます。
- var n = 0;
ul
while n < 4
li= n++
↓
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Extends
extends
で型として作った別ファイルを呼び出してデータを流し込むことができます。主に基本構造を _layout.pug
として用意してページを量産する場合に使います。
//- _layout.pug
doctype html
block vars
html(lang="ja")
head
include _head.pug
body(class=site.body class=page.body)
block contents
include _script.pug
//- index.pug
extends /base/_layout.pug
block vars
include /base/_config.pug
- var key = "index"
- var page = pages[key]
block contents
Mixin
mixin
で型を用意して使い回すことができます。主に細かいモジュールの繰り返しで使います。
mixin pet(name)
li.pet= name
ul
+pet('cat')
+pet('dog')
+pet('pig')
↓
<ul>
<li class="pet">cat</li>
<li class="pet">dog</li>
<li class="pet">pig</li>
</ul>
Piped Text
|
を先頭に書くことによって文章やタグを改行せずに出力できます。長文の管理や、途中にリンクタグを入れる場合に便利です。
p
| 文章の途中に
a(href="#") リンクタグ
| を入れる。
↓
<p>文章の途中に<a href="#">リンクタグ</a>を入れる。</p>
Block in a Tag
タグの末尾を .
にすることで、内包する要素の Pug 構文を解除できます。主に、インラインでスタイルやスクリプトを書く場合に使用します。
script.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'UA-XXXXXXXX-XX');
↓
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'UA-XXXXXXXX-XX');
</script>
Markdown
gulp 等では、jstransformer-markdown-it
をインストールし Pug 内で Markdown を書く・Markdown ファイルを読み込むことができます。
$ npm i -D jstransformer-markdown-it
.wysiwyg
:markdown-it
## ソースコード
MarkdownがPug内で書けるとは。
include:markdown-it article.md
↓
<div class="wysiwyg">
<h2>ソースコード</h2>
<p>MarkdownがPug内で書けるとは。</p>
<h3>読み込んだMarkdown</h3>
<p>読み込んだMarkdownテキスト。</p>
</div>
:markdown-it
に続けてオプションを設定できます。よく使うオプションは以下。
option | default | detail |
---|---|---|
html | false | Markdown 内で HTML タグを有効にする |
breaks | false | 改行箇所に <br/> タグを差し込む |
langPrefix | 'language-' | コードブロックにプレフィックス class を付与 |
linkify | false | URL を自動的に <a> タグへ変換 |
.wysiwyg
:markdown-it(breaks="true")
## ソースコード