More than 1 year has 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に監視させて、オートリロードとかにしてるとエラーしてるのに気がつかなくて修正が反映されなくて焦ることが合ったかもしれませんが、これで大丈夫です!

エラーでささくれた気持ちもパグで癒やされること間違いなしですよ!

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