必ず覚えるべきPug(Jade)でよく使う正しい9つの書き方

Pugとは

Pugは短い記法でHTMLを生成できるテンプレートエンジン。

Sassを知っている人ならSassのHTML版のようなものと言えばわかりやすい。

例えば.pugファイルを作成して以下のように記述すると

.foo
  p.bar sample

以下のようなHTMLを生成できる。

<div class="foo">
    <p class="bar">sample</p>
</div>

Pugはオンラインジェネレーターがあるので、ここで試しにHTMLに生成すれば理解が早いだろう。

https://pughtml.com/

Pugのオンラインジェネレーターはたくさんあるが、旧式のJadeのジェネレーターだと正しく変換されないことがあるので使用しないほうが良いです。

実際のWebページの確認であれば以下のコマンドを実行すればwebpackでpugをhtmlに変換してブラウザで確認する環境が作成できる。

mkdir pug-test; cd pug-test; npm init -y; npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin pug-html-loader pug-loader; mkdir src; touch src/index.js index.pug webpack.config.js;

webpack.config.jsの中身は以下のように記述。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development",
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.pug$/,
        use: [
          {
            loader: "pug-loader",
            options: {
              pretty: true,
            },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./index.pug",
      filename: "index.html",
    }),
  ],
};

あとはwebpack s --openを実行すればブラウザでページが開くので、index.pugを修正するたびにindex.htmlが生成されてブラウザで確認できるようになる。

webpack s --open

例えばindex.pugに以下のコードを記述すると…

html(lang="ja")
  head
    meta(charset="utf-8")
    title sample
  body
    h1 sample

書き出されるHTMLは以下のようになる。※

※ 実際はwebpackの自動挿入による<script defer src="main.js"></script>も含まれますが、この記事ではコードを見やすいよう省いています。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>sample</title>
  </head>
  <body>
    <h1>sample</h1>
  </body>
</html>

コメントの書き方

pugではHTMLの<!-- -->を使用した場合はHTMLにコードが残らない。

HTMLコメントを残したい場合は // を使用する。

//- にするとコメントが残らない。

index.pug

<!-- コメント(表示されない) -->
p コメント(表示されない)

// コメント(表示される)
p コメント(表示される)

//
  複数行のコメントは//のあとに改行とインデントで表現できる。
  Sass(CSS)のように/* */は使用不可。
  このコメントはHTMLコード内に残る。

//-
  複数行のコメントが//-だと
  HTMLコード内にコメントが残らない。

index.html

<!-- コメント(表示されない) -->
<p>コメント(表示されない)</p>
<!-- コメント(表示される)-->
<p>コメント(表示される)</p>
<!--
複数行のコメントは//のあとに改行とインデントで表現できる。
Sass(CSS)のように/* */は使用不可。
このコメントはHTMLコード内に残る。

-->

属性を追加する

属性を追加する場合はimg(src="https://iwb.jp/s/sample.jpg" alt="sample")のようにタグのあとに()で指定。

index.pug

img(src="https://iwb.jp/s/sample.jpg" alt="sample")

index.html

<img src="https://iwb.jp/s/sample.jpg" alt="sample">

属性が多い場合は括弧内で改行して、このように書くこともできる。

img(
  id="foo"
  class="bar"
  src="https://iwb.jp/s/sample.jpg"
  alt="sample"
)

&attributesで属性追加

&attributesを使用することでも属性を追加できる。

複数のタグに同じ属性を指定する際は&attributesを使用すれば同じ属性を何回も書かなくて済む。

index.pug

- const attrs = {
-   'class': 'foo',
-   'src': 'https://iwb.jp/s/sample.jpg',
-   'alt': 'sample',
- };

img(id="foo1")&attributes(attrs)
img(id="foo2")&attributes(attrs)

index.html

<img class="foo" id="foo1" src="https://iwb.jp/s/sample.jpg" alt="sample"><img class="foo" id="foo2" src="https://iwb.jp/s/sample.jpg" alt="sample">

インラインの記述について

タグのあとに記述するテキスト内の一部をタグで囲みたい場合、直接タグで囲むこともできるが、#[strong pen] のようにpugの記述を使用すれば短くかける。

index.pug

p This is a <strong>pen</strong> and pencil.

p This is a #[strong pen] and pencil.

index.html

<p>This is a <strong>pen</strong> and pencil.</p>
<p>This is a <strong>pen</strong> and pencil.</p>

テキストが長すぎる場合は改行して | を追加して続きを書けばタグ内に収まる。

index.pug

p さぞ時間で逡巡院はもしその安心ありありだけに
  | 移ればいですからも推察しですですて、
  | まだには知れたんたでしょ。

index.html

<p>
  さぞ時間で逡巡院はもしその安心ありありだけに移ればいですからも推察しですですて、
  まだには知れたんたでしょ。
</p>

YouTube動画のiframeなどのHTMLタグはpugで書き直すのは手間なので.(ドット)を入れて改行してインデントを入れたあと、そのまま貼り付ける。

.
  <iframe width="560" height="315" src="https://www.youtube.com/embed/Z9ki00Z5SWg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

スタイル属性

スタイル属性はh1(style={color: red})のように追加する。

改行を入れて以下のように書くことも可能。

index.pug

h1(style={
  "color": "red",
  "font-size": "3em"
}) sample

index.html

<h1 style="color:red;font-size:3em;">sample</h1>

エスケープ

タグに = をつけて h='& < > "' と書けばエスケープされる。
( ' で囲まないと正しくエスケープされない)

「'」と「`」はエスケープされないので注意。

index.pug

h1= '& < > "'

index.html

<h1>&amp; &lt; &gt; &quot;</h1>

エスケープしない場合は「h1!=」だがセキュリティの関係上、通常は使用しない。

includeでpugファイルを読み込み

includeで.pugファイルを指定することで読み込むことができる。

index.pug


head.pug

//- head.pug
head
  title Sample

foot.pug

//- foot.pug
footer
  p (c) iwb.jp

index.html

<!DOCTYPE html>
<html>
<head>
  <title>Sample</title>
</head>
  <body>
    <h1>Sample Site</h1>
    <p>Hello world!</p>
<footer>
  <p>(c) iwb.jp</p>
</footer>
  </body>
</html>

constで定数を指定

pugファイル内に- const name = 'Ken'で定数を指定できる。

varを指定しているサンプルを見かけることがあるが、特に理由がなければ値が変わらない定数を使用したほうが良い。

index.pug

- const name = 'Ken'

p Hello #{name}!

index.html

<p>Hello Ken!</p>

先頭にハイフンがあるとJavaScriptで色々な指定を記述できるのでMapなども使用できる。

- const animal = new Map()
- animal.set('犬')

- if (animal.has('犬'))
  p 犬を飼っています。
- else
  p 犬を買っていません。

配列も使用できるのでforやeachを使えば以下のような記述もできる。

条件分岐などがなければ記述の短いeachを使用する。

「- for」と「each」とハイフンの有無に注意。

index.pug

- const arr = ['foo', 'bar', 'baz']

ul
  - for (var i = 0; i < arr.length; i++)
    li #{arr[i]}

ul
  each value in arr
    li #{value}

index.html

<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
</ul>
<ul>
  <li>foo</li>
  <li>bar</li>
  <li>baz</li>
</ul>

属性の場合はそのまま指定するか`${ }`で指定。(#{ }で指定するとエラーになる)

index.pug

- const inputType = 'number'

input(type=inputType)

input(type=`${inputType}`)

//- input(type=#{inputType}) はエラーになる

index.html

<input type="number">
<input type="number">

条件分岐

if, else if, elseで条件分岐できる。

index.pug

- const author = '鈴木'

if author === '佐藤'
  p 記事の作者は#{author}編集長
else if author === '鈴木'
  p 記事の作者は#{author}副編集長
else if author
  p 記事の作者は#{author}
else
  p 記事の作者は不明

index.html

<p>記事の作者は鈴木副編集長</p>

カテゴリーhtml