#2017/06/23追記
今更ですが、本記事のサンプルコードをあげました
soarflat-prototype/pug-template
サンプルコードは以下の点で記事内容と異なります。
- 拡張子がpug
- mixinを利用する必要がなかったため利用していない
- 現在のバージョンだと
"http://#{metas.url}"
のような"#{}"
がサポートされていないため修正
はじめに
Pugの勉強のためにHTMLのテンプレート的なのをJadeで書きました。
Pugで書くとこうなる
もとのHTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="author" content="">
<meta property="og:title" content="タイトル">
<meta property="og:type" content="website">
<meta property="og:url" content="http://任意のURL">
<meta property="og:image" content="http://任意のURL/og_image.png">
<meta property="og:site_name" content="">
<meta property="og:description" content="" />
<meta property="fb:app_id" content="任意のID">
<title>タイトル</title>
<link rel="stylesheet" href="css/style.css">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
</script>
</head>
<body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script> (window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>')); </script>
<script src="js/scripts.js"></script>
</body>
</html>
これをPugで書くと以下のようになる。
doctype
html(lang="ja")
head
meta(charset="utf-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
meta(name="viewport", content="width=device-width, initial-scale=1")
meta(name="description", content="")
meta(name="keywords", content="")
meta(name="author", content="")
meta(property="og:title", content="タイトル")
meta(property="og:type", content="website")
meta(property="og:url", content="http://任意のURL")
meta(property="og:image", content="http://任意のURL/og_image.png")
meta(property="og:site_name", content="")
meta(property="og:description", content="")
meta(property="fb:app_id", content="任意のID")
title タイトル
link(rel='stylesheet', href="css/style.css")
script.
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
body
script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js")
script.
(window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>'));
script(src="js/scripts.js")
比較してみると、ただPug記法になっただけなので「Pugで書く必要なくない?」状態。
Pugらしい書き方になるようにする。
Pugらしい書き方で書くとこうなる
extends _layout
block var
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
block append meta
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
block title
title
block body
block var
doctype html
html(lang="ja")
head
meta(charset='utf-8')
meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
meta(name="viewport", content="width=device-width, initial-scale=1")
block meta
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
block title
block link
link(rel='stylesheet', href="css/style.css")
block head_script
script.
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
body
block body
block end_of_body
script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js")
script.
(window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>'));
script(src="js/scripts.js")
mixin inc_meta_facebook(metas)
meta(property="og:title", content=metas.title)
meta(property="og:type", content="website")
meta(property="og:url", content="http://#{metas.url}")
meta(property="og:image", content="http://#{metas.image}/og_image.png")
meta(property="og:site_name", content=metas.site_name)
meta(property="og:description", content=metas.description)
meta(property="fb:app_id", content="任意のID")
ディレクトリ構成は以下を前提とする。
.
├── index.pug
├── _layout.pug
└── _inc_meta_facebook.pug
Pugらしい書き方になった。(自信はない)
コンパイルされるHTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="description">
<meta name="keywords">
<meta name="author" content="">
<meta property="og:title" content="title">
<meta property="og:type" content="website">
<meta property="og:url" content="http://url">
<meta property="og:image" content="http://image/og_image.png">
<meta property="og:site_name" content="site_name">
<meta property="og:description" content="description">
<meta property="fb:app_id" content="任意のID">
<title></title>
<link rel="stylesheet" href="css/style.css">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
</script>
</head>
<body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>(window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>'));</script>
<script src="js/scripts.js"></script>
</body>
</html>
mixinの箇所にインデントが発生していまうのが気になる。
今回利用したPugの機能
- 変数
- include
- extends
- block
- mixin
変数
Pugでは変数が利用できる。
今回の例では変数metas
が存在する。
extends _layout
block var
//- 変数metas
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
block append meta
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
block title
title
block body
include
他のPugファイルを読み込む。
extends _layout
block var
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
block append meta
+meta(metas)
//- _inc_meta_facebook.pugを読み込む。
include _inc_meta_facebook
+inc_meta_facebook(metas)
block title
title
block body
今回の例ではinclude _inc_meta_facebook
と記述されているため、
_inc_meta_facebook.pug
が読み込まれる。
mixin inc_meta_facebook(metas)
meta(property="og:title", content=metas.title)
meta(property="og:type", content="website")
meta(property="og:url", content="http://#{metas.url}")
meta(property="og:image", content="http://#{metas.image}/og_image.png")
meta(property="og:site_name", content=metas.site_name)
meta(property="og:description", content=metas.description)
meta(property="fb:app_id", content="任意のID")
extendsとblock
他のPugファイルを継承する。
//- _layout.pugを敬承する。
extends _layout
block var
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
block append meta
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
block title
title
block body
今回の例ではextends _layout
と記述されているため、
index.pug
に_layout.pug
が継承される。
block var
doctype html
html(lang="ja")
head
meta(charset='utf-8')
meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
meta(name="viewport", content="width=device-width, initial-scale=1")
block meta
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
block title
block link
link(rel='stylesheet', href="css/style.css")
block head_script
script.
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
body
block body
block end_of_body
script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js")
script.
(window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>'));
script(src="js/scripts.js")
include
のように他のPugファイルを読み込むが、include
とは異なり、
継承先ファイルと継承元ファイルの同じ名前のblock
が紐づく。(関連付く?)
継承先と継承元のblockの関係
敬承先に敬承元と同じ名前のblock
が存在しない場合、敬承元のblock
内の記述が読み込まれるが
敬承先にも同じ名前のblock
が存在する場合、block
内の記述が上書きされる。
今回の例だと上書きされるのはblock var
、block title
、block body
内の記述。
extends _layout
//- block varを上書きする。
block var
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
block append meta
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
//- block titleを上書きする。
block title
title
//- block bodyを上書きする。
block body
//- 敬承先にblock varが存在するため、敬承先に読み込まれない。
block var
doctype html
html(lang="ja")
head
meta(charset='utf-8')
meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
meta(name="viewport", content="width=device-width, initial-scale=1")
block meta
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
//- 敬承先にblock titleが存在するため、敬承先に読み込まれない。
block title
//- 敬承先にblock linkは存在しないため、敬承先に読み込まれる。
block link
link(rel='stylesheet', href="css/style.css")
//- 敬承先にblock head_scriptは存在しないため、敬承先に読み込まれる。
block head_script
script.
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
body
//- 敬承先にblock bodyが存在するため、敬承先に読み込まれない。
block body
//- 敬承先にblock end_of_bodyは存在しないため、敬承先に読み込まれる。
block end_of_body
script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js")
script.
(window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>'));
script(src="js/scripts.js")
敬承先に敬承元と同じ名前のblock
が存在する場合、
敬承先のblock
内に記述自体がなくても、敬承元のblock
内の記述は読みこまれないので注意。
block append
block
と異なり、記述を上書きをするのではなく
敬承元の記述の後に敬承先の記述を追加できる。
extends _layout
block var
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
//- 敬承元のblock meta内の記述の後にblock append meta内の記述が追加される。
block append meta
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
block title
title
block body
block var
doctype html
html(lang="ja")
head
meta(charset='utf-8')
meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
meta(name="viewport", content="width=device-width, initial-scale=1")
//- 敬承先にblock append metaが存在するため、敬承先に読み込まれる。
block meta
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
block title
block link
link(rel='stylesheet', href="css/style.css")
block head_script
script.
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-Y', 'example.com');
ga('send', 'pageview');
body
block body
block end_of_body
script(src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js")
script.
(window.jQuery || document .write('<script src="js/jquery-1.11.2.min.js"><\/script>'));
script(src="js/scripts.js")
イメージとしては以下のようになる。
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
block prepend
敬承元の記述の前に敬承先の記述を追加できる。
block append meta
をblock prepend meta
にすると
イメージとしては以下のようになる。
+meta(metas)
include _inc_meta_facebook
+inc_meta_facebook(metas)
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
mixin
関数のような再利用できるblock
を生成できる。
今回の例では_layout.pug
にmixin meta(metas)
が存在し、
mixin meta(metas)
meta(name="description", content=metas.description)
meta(name="keywords", content=metas.keywords)
meta(name="author", content="")
_inc_meta_facebook.pug
にmixin inc_meta_facebook(metas)
が存在する。
mixin inc_meta_facebook(metas)
meta(property="og:title", content=metas.title)
meta(property="og:type", content="website")
meta(property="og:url", content="http://#{metas.url}")
meta(property="og:image", content="http://#{metas.image}/og_image.png")
meta(property="og:site_name", content=metas.site_name)
meta(property="og:description", content=metas.description)
meta(property="fb:app_id", content="任意のID")
mixinを利用する時は、+
を記述する。
今回の例ではblock append meta
内で
mixin meta(metas)
とmixn inc_meta_facebook(metas)
内の記述が追加される。
extends _layout
block var
- metas = {}
- metas.title = 'title'
- metas.url = 'url'
- metas.image = 'image'
- metas.site_name = 'site_name'
- metas.description = 'description'
block append meta
//- block var内の変数metasが引数として渡され、
//- mixin meta(metas)内の記述が追加される。
+meta(metas)
include _inc_meta_facebook
//- block var内の変数metasが引数として渡され、
//- mixn inc_meta_facebook(metas)内の記述が追加される。
+inc_meta_facebook(metas)
block title
title
block body