Help us understand the problem. What is going on with this article?

Pugと仲良くする方法

More than 3 years have passed since last update.

この記事は J2complexed Advent Calendar 2016 の14日目の記事です。

みなさんはパグと仲良くできていますか?
パグはかわいいですね。なによりもマークアップの効率が良くなります!
Pugは以前までJadeと名乗っていましたが、Pugの方がいいですね。いいセンスをしてます。
詳しくは公式を見ていただいたほうが、いいと思います!
pug.png

Getting Started - Pug

Pugの簡単な紹介

PugはJST (JavaScript Templates)って言われてるJavaScriptで動くテンプレートエンジンです。
Expressでも動かすことができます。(動かしたことはありませんが)
Express でのテンプレート・エンジンの使用

Githubに載っている例を見てみると、書き方がわかると思います。

example.pug
doctype html
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) bar(1 + 5)
  body
    h1 Pug - node template engine
    #container.col
      if youAreUsingPug
        p You are amazing
      else
        p Get on it!
      p.
        Pug is a terse and simple templating language with a
        strong focus on performance and powerful features.

これが、こうなります。

example.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Pug</title>
    <script type="text/javascript">
      if (foo) bar(1 + 5)
    </script>
  </head>
  <body>
    <h1>Pug - node template engine</h1>
    <div id="container" class="col">
      <p>You are amazing</p>
      <p>Pug is a terse and simple templating language with a strong focus on performance and powerful features.</p>
    </div>
  </body>
</html>

この例でわかるところといえば、以下でしょうか。

  • 閉じタグがいらない
  • インデントが重要
  • classやidはCSSセレクタと同じ
  • 属性は()の中で書く
  • if文で分岐ができる
  • 変数を使える
  • .を付けると、次のインデントは文字列としてそのまま出力できる
  • divは省略できる

例にはありませんでしたが、for文も書けますよ!

Pugでテンプレートをつくる

Pugについて理解が深まったところで、さらに仲良くなるためにテンプレートの用意です。
※ これは自己流なので、よりよい方法をご存じの方、情報をお待ちしてます

簡単に概要を説明すると、まず、 パーツのpug を用意して、 レイアウトのpug に読み込ませます。
次に 設定ファイルのpug実際にhtml化するpug に読み込ませて、 レイアウトのpug を継承させます。
・・・なんだかごちゃごちゃしてますが、用意するファイルはこんな感じです。

index.pug         ・・・ 実際にhtml化するpug
_config.pug       ・・・ 設定ファイルのpug
_layout.pug       ・・・ レイアウトのpug
include/          ・・・ パーツのpugのディレクトリ
  _inc_head.pug
  _inc_header.pug
  _inc_nav.pug
  _inc_footer.pug

パーツを用意

パーツを分けておきます。Pugはincludeで別のpugやhtmlを読み込むことができるので、いろいろと使いまわすことができるのです。

_inc_head.pug

headタグ内のパーツです。pageというオブジェクトから値を受け取ってセットしています。
keyやcss_path、domainも変数です。

_inc_head.jade
meta(charset="utf-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
meta(name="format-detection", content="telephone=no")

title #{page.title}

meta(content=page.description, name="description")
meta(content=page.keywords, name="keywords")
meta(content=page.title, property="og:title")
meta(content=page.description, property="og:description")
meta(content=domain + page.image, property="og:image")
meta(content=domain + page.url, property="og:url")
meta(content=(key == "top" ? "website" : "article"), property="og:type")
meta(content="ja_JP", property="og:locale")

link(rel="stylesheet", href=css_path+"/style.css")
script(src="https://code.jquery.com/jquery-1.11.2.min.js")

_inc_header.pug

次にheaderタグのパーツです。
pages、image_pathも変数です。

_inc_header.pug
header
  .header_logo
    if key=='top'
      h1
        a(href=pages.top.url)
          img(src=image_path+"/shared/header_logo.png" alt=pages.top.name)
    else
      p
        a(href=pages.top.url)
          img(src=image_path+"/shared/header_logo.png" alt=pages.top.name)

_inc_nav.pug

次にnavタグのパーツです。
content_d_stateも変数で、状況に応じて出力するタグの内容が変わったりすることもテンプレートに埋め込んでおけます。便利。

_inc_nav.pug
nav
  ul
    li
      a(href=pages.content_a.url)
        img(src=image_path+"/shared/nav_content_a.png", alt=pages.content_a.name)
    li
      a(href=pages.content_b.url)
        img(src=image_path+"/shared/nav_content_b.png", alt=pages.content_b.name)
    li
      a(href=pages.content_c.url)
        img(src=image_path+"/shared/nav_content_c.png", alt=pages.content_c.name)
    if content_d_state=="public"
      li
        a(href=pages.content_d.url)
          img(src=image_path+"/shared/nav_content_d_public.png" alt=pages.content_d.name)
    else if content_d_state=="comingsoon"
      li
        img(src=image_path+"/shared/nav_content_d_comingsoon.png" alt=pages.content_d.name+" Coming Soon...")

_inc_nav.pug

次にfooterタグのパーツです。
js_pathも変数です。

_inc_footer.pug
footer
  p
    small copyright
script(type='text/javascript' src=js_path+"/js/functions.js")

設定ファイルを用意

titleやページのurlなど、変更があったときにファイルが分かれていると不便ですよね。
そんなときのために、変数をまとめてあります。

var で変数が宣言できます。

_config.pug
- var image_path = 'assets/img'
- var css_path = 'assets/css'
- var js_path = 'assets/js'
- var domain = 'https://example.com/'
- var content_d_state = "comingsoon"
- 
  var pages = {
    top : {
      url : 'index.html',
      name : 'トップページ',
      title : 'トップページ',
      description : 'トップページです',
      keywords : 'トップページ',
      image : 'assets/img/ogp.jpg'
    },
    content_a : {
      url : 'content_a.html',
      name : 'コンテントA',
      title : 'コンテントA',
      description : 'コンテントAです',
      keywords : 'コンテントA',
      image : 'assets/img/ogp.jpg'
    },
    content_b : {
      url : 'content_b.html',
      name : 'コンテントB',
      title : 'コンテントB',
      description : 'コンテントBです',
      keywords : 'コンテントB',
      image : 'assets/img/ogp.jpg'
    },
    content_c : {
      url : 'content_c.html',
      name : 'コンテントC',
      title : 'コンテントC',
      description : 'コンテントCです',
      keywords : 'コンテントC',
      image : 'assets/img/ogp.jpg'
    },
    content_d : {
      url : 'content_d.html',
      name : 'コンテントD',
      title : 'コンテントD',
      description : 'コンテントDです',
      keywords : 'コンテントD',
      image : 'assets/img/ogp.jpg'
    }
  }

レイアウトファイルを用意

レイアウトっていうと分かりにくいかもしれませんが、パーツを組み合わせる骨組みみたいなものです。
ここで、 block という新しい言葉が出てきます。
ブロックに varscontents という名前を付けておいて、あとで読み込む事ができます。

_layout.pug
doctype html
block vars
html(lang="ja")
  head
    include _inc_head.pug

  body(class=key)
    .l_contents
      include _inc_header.pug
      include _inc_nav.pug
      block contents
    include _inc_footer.pug

実際にHTMLにするファイルを用意

extendでレイアウトファイルを継承してます。
継承後にblockでレイアウト側に送るイメージです。

index.pug
extends _layout.pug

block vars
  include ./template/_config.pug
  - var key = "top"
  - var page = pages[key]

block contents
  h2 page.title
  .keyvisual_container
    p.keyvisual_image
      img(src=image_path+"/top/top_keyvisual.jpg", alt="")

gulpで実行

package.jsonから必要なものをインストールします。
見慣れないものが混じっているかもしれませんが、入れましょう。

package.json
{
  "name": "love-pug",
  "version": "1.0.0",
  "description": "i love pug",
  "main": "index.js",
  "scripts": {
    "gulp": "gulp"
  },
  "keywords": [
    "pug"
  ],
  "author": "j2complexed",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.18.5",
    "gulp": "^3.9.1",
    "gulp-plumber": "^1.1.0",
    "gulp-pug": "^3.2.0",
    "node-notifier": "^4.6.1"
  }
}

上記のファイルを用意したらコマンドでインストールです。

$ npm install

次にgulpを実行するための設定をします。
このままコピペです。

gulpfile.js
const gulp = require('gulp');
const browserSync = require("browser-sync");
const plumber = require('gulp-plumber');
const pug = require('gulp-pug');
const notifier = require('node-notifier');

const errorHandler = function(error) {
    notifier.notify({
      message: 'しっぱいしたワン',
      title: 'パグ',
      appIcon: __dirname + '/pug.png',
    }, function () {
      console.log(error.message);
    });
  };

gulp.task('browser-sync', () => {
    browserSync({
        server: {
            baseDir: "./dist/"
        }
    });
    gulp.watch("./*.html", browserSync.reload);
});

gulp.task('views', function() {
  return gulp.src(['views/**/*.pug', '!views/**/_*.pug'])
    .pipe(plumber({errorHandler: errorHandler}))
    .pipe(pug({pretty: true}))
    .pipe(gulp.dest('dist/'));
});

gulp.task('watch', () => {
  gulp.watch(['./views/**/*.pug'], () => {
    gulp.start(['views']);
  });
});

gulp.task('default', ['browser-sync', 'views', 'watch']);

あとはコマンドで実行です。

$ npm run gulp

そうすると、distというディレクトリにindex.htmlができて、ブラウザが起動し http://localhost:3000/ が開いたと思います。
cssとかはないので、崩れているとは思いますが。

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="format-detection" content="telephone=no">
    <title>トップページ</title>
    <meta content="トップページです" name="description">
    <meta content="トップページ" name="keywords">
    <meta content="トップページ" property="og:title">
    <meta content="トップページです" property="og:description">
    <meta content="https://example.com/assets/img/ogp.jpg" property="og:image">
    <meta content="https://example.com/index.html" property="og:url">
    <meta content="website" property="og:type">
    <meta content="ja_JP" property="og:locale">
    <link rel="stylesheet" href="assets/css/style.css">
    <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
  </head>
  <body class="top">
    <div class="l_contents">
      <header>
        <div class="header_logo">
          <h1><a href="index.html"><img src="assets/img/shared/header_logo.png" alt="トップページ"></a></h1>
        </div>
      </header>
      <nav>
        <ul>
          <li><a href="content_a.html"><img src="assets/img/shared/nav_content_a.png" alt="コンテントA"></a></li>
          <li><a href="content_b.html"><img src="assets/img/shared/nav_content_b.png" alt="コンテントB"></a></li>
          <li><a href="content_c.html"><img src="assets/img/shared/nav_content_c.png" alt="コンテントC"></a></li>
          <li><img src="assets/img/shared/nav_content_d_comingsoon.png" alt="コンテントD Coming Soon..."></li>
        </ul>
      </nav>
      <h2>page.title</h2>
      <div class="keyvisual_container">
        <p class="keyvisual_image"><img src="assets/img/top/top_keyvisual.jpg" alt=""></p>
      </div>
    </div>
    <footer>
      <p><small>copyright</small></p>
    </footer>
    <script type="text/javascript" src="assets/js/js/functions.js"></script>
  </body>
</html>

どうでしょう!テンプレートが完成です!
他のページを作るときには、 extends _layout.puginclude _config.pug のディレクトリに気をつけて貰えば、コピペでテンプレートを使うことができます!

もっと仲良くなりたい人のために

先ほどの gulpfile.js でお気づきかもしれませんが、コンパイルに失敗すると、パグが失敗したことを通知で教えてくれます。
pug.gif

よくgulpに監視させて、オートリロードとかにしてるとエラーしてるのに気がつかなくて修正が反映されなくて焦ることが合ったかもしれませんが、これで大丈夫です!
エラーでささくれた気持ちもパグで癒やされること間違いなしですよ!

※ 読み込むアイコン画像は各自で用意してくださいね!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした