Nice Page Builderをブログ書きながらテストしていったよ
目次を追加してマークアップを修正、併せて追記と修正を行っています。(2021.5.11)
諸々公開しています。(2017.2.2)
- 最小のパターン
- 任意のプロパティを追加してみる
- 各ページで共通する値を別ファイルに分離したい
MIXINS
- ルート相対リンクから相対リンクへ変換
beforeBuild
スクリプトとPage
クラスの拡張
現在 Nice Page Builder は自分のホームページ開発に使っています。生憎とコードが散らかっているので公開はもうちょい先になります。
1. 最小のパターン
npmTestProject - source templete.html index.html - output index.html
まずは最低限の機能、テンプレートだけな HTML とコンテンツだけの HTML から完成版の HTML を生成します。
source/templete.html
<!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<main>{$$ this.CONTENT $$}</main>
<footer></footer>
</body>
</html>
テンプレート側からコンテンツは this.CONTENT
または page.CONTENT
で取得します。
source/index.html
<script type="nice-page-builder/object" for="page-option">
{
TEMPLETE : '/templete.html'
}
</script>
<p>Hello, World!
テンプレートへの参照は上の通り <script>
要素内のオブジェクトリテラルで行います。独自の type
と for
属性が付いています。
この独自 <script>
要素の内容は生成過程で評価・破棄されて生成物に含まれることはありません。
output/index.html
18日(日)夕までに先の2つのファイルから次の index.html を得ることが出来ました。
<!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<main>
<p>Hello, World!</main>
<footer></footer>
</body>
</html>
2. 任意のプロパティを追加してみる
次に任意のプロパティの使い方を見ていきます。これはサイト開発者がプロジェクト毎に独自に定義していきます。
source/index.html
<script type="nice-page-builder/object" for="page-option">
{
TEMPLETE : '/templete.html',
title : 'Hello'
}
</script>
<p>Hello, World!
ページ毎にタイトルを変えたいので(当たり前ですね)、title
というプロパティを追加します。
source/templete.html
<!DOCTYPE html>
<script type="nice-page-builder/object" for="page-option">
{
title : 'No Title!'
}
</script>
<html>
<head><title>{$$ this.title $$}</title></head>
<body>
<header><h1>{$$ this.title $$}</h1></header>
<main>{$$ this.CONTENT $$}</main>
<footer></footer>
</body>
</html>
テンプレートで title
文字列を挿入したい位置に追記していきます。またデフォルトのタイトルがある場合、テンプレートに書いておきます。
output/index.html
Hello が挿入されていること、source/index.html で title
を指定しなかった場合、No Title! が代わりに挿入されていることを確認できました。
<!DOCTYPE html>
<html>
<head><title>Hello</title></head>
<body>
<header><h1>Hello</h1></header>
<main>
<p>Hello, World!</main>
<footer></footer>
</body>
</html>
3. 各ページで共通する値を別ファイルに分離したい MIXINS
DreamWeaver でいうところのライブラリ機能のように各ページで共通して使う値を分離することができます。
トップページ(index.html)の他に商品の紹介ページ(今回はペン、パイナップル、アップルの計3ページ)を持つ企業サイトを例にします。
npmTestProject - source templete.html index.html products apple.html pen.html pineapple.html mixins products.json - output index.html products apple.html pen.html pineapple.html
source/templete.html
<!DOCTYPE html>
<script type="nice-page-builder/object" for="page-option">
{
title : 'No title!'
}
</script>
<html>
<head><title>{$$ (this.category ? this.category + ' > ' : '' ) + this.title $$}</title></head>
<body>
<main>{$$ this.CONTENT $$}</main>
</body>
</html>
新しいプロパティ category
を追加します。三項式を使って <title>
に出力されるようにしました。
source/products/apple.html
<script type="nice-page-builder/object" for="page-option">
{
MIXINS : ['/mixins/products.json'],
title : 'Apple'
}
</script>
<p>This is a Apple.
MIXINS
というビルトインプロパティで商品紹介ページに共通する値を持つ "/mixins/products.json"
のパスを書きます。
source/mixins/products.json
{
"TEMPLETE" : "/templete.html",
"category" : "商品紹介",
"title" : "商品の title がありません"
}
ミックスインの内容はページのプロパティにコピーされます。ページ側ですでにプロパティが定義されている場合、上書きされることはありません。優先順位は ページ > ミックスイン[0] > ミックスイン[z] > テンプレートです。
json の書き方がめんどくさい場合、js のオブジェクトリテラルで書いてしまっても構いません。その際はエディタの構文チェックが警告してくるのでファイル名を products.js にします。
output/products/apple.html
<!DOCTYPE html>
<html>
<head><title>商品紹介 > pineapple</title></head>
<body>
<main>
<p>This is a pineapple.</main>
</body>
</html>
4. ルート相対リンクから相対リンクへ変換
ここまでのテストでフォルダ階層ができたのでリンクの変換を CSS の追加をダシに確認します。
npmTestProject - source templete.html index.html products apple.html pen.html pineapple.html mixins products.json - output index.html products apple.html pen.html pineapple.html css all.css
output/css/all.css
output/css 下に次のファイルを追加しました。
body { background: yellow; color : darkgoldenrod; }
source/templete.html
続いて <link>
をテンプレートに追加します。この際にリンクをソースのルートフォルダからのルート相対リンクで指定して ($$ ~ $$)
で挟みます。
<link rel="stylesheet" type="text/css" href="($$ /css/all.css $$)">
テンプレートは様々な階層から参照されます。その際にパスがズレない為のルート相対リンクです。
/index.html では <link rel="stylesheet" type="text/css" href="css/all.css">
が products/*.html では <link rel="stylesheet" type="text/css" href="../css/all.css">
が追加されました。
5. beforeBuild
コールバックと Page
クラスの拡張
インラインスクリプト({$$ /* inline script */ $$}
)では長々とスクリプトを書くには適しません。また同じ内容のインラインスクリプトが複数ある場合メソッドにまとめたいところです。
次のように <script type="nice-page-builder/js" for="beforeBuild">
内にスクリプトを書きます。ここに書かれたスクリプトは pages
と Page
のグローバル変数にアクセスできます。
pages
を for in
ループで回して集計をしたり、Page.prototype
に値やメソッドを追加できます。
<!DOCTYPE html>
<script type="nice-page-builder/object" for="page-option">
{
title : 'No title!'
}
</script>
<script type="nice-page-builder/js" for="beforeBuild">
// 全ページのリンクを取得
var links = [], path, label;
for( path in pages ){
links.push({title:pages[path].title,path:pages[path].FILE_PATH});
};
// リンクリストを書きだすメソッドの追加
Page.prototype.ALL_LINK = links;
Page.prototype.createLinkList = function(){
var html = [], i = -1, link;
for( ; link = this.ALL_LINK[++i]; ){
if( link.path !== this.FILE_PATH )
html.push('<a href="'+ this.toRelativePath(link.path) + '">' + link.title + '</a>');
};
return html.join(',');
};
</script>
<html>
<head>
<title>{$$ (this.category ? this.category + ' > ' : '' ) + this.title $$}</title>
<link rel="stylesheet" type="text/css" href="($$ /css/all.css $$)">
</head>
<body>
<main>{$$ this.CONTENT $$}</main>
<footer>{$$ this.createLinkList() $$}</footer>
</body>
</html>