Bloggerのテンプレートを最小化
Bloggerのテーマは色やサイズ等カスタムもでき便利なのですが、テーマがレスポンシブデザインに対応していないことがあったり、使わない機能が消せなかったりと、逆にそれに制限されてしまうこともあります。
今回はそのような制限から逃るために、独自のページの土台となる最小限のテンプレートXMLを作成します。
Bloggerの構造
Bloggerの構造は、投稿データとそれにまつわるタグなどのメタデータ、画像、テンプレートXMLの大きく3つに分類されます。
ページにアクセスがあると、投稿データやメタデータを読みだし、それをユーザー毎に設定されているテンプレートXMLに当てはめてページを作成します。
画像データに関してはおおむね一般的なWebサーバーと同じ運用ですが、アップロード時に機械的な名前を付けられ、Google photoのアーカイブ領域に保存されたものが表示されます。
テンプレートXML
テンプレートXMLは通常のHTMLの書式に準じた記述の他、Bloggerがページを構成する際に使われる処理命令も記述します。
また、Bloggerのインターフェースからテーマをカスタマイズし背景や文字色などの設定を変更した場合も、その情報がここに記述され、ページ表示時にCSSとして書き起こされます。
これらの「テーマ」をカスタマイズするために設けられている構造は、その意図通りに使う分には便利なのですが、そこから離れて一から自分のオリジナルのページを作ろうとする場合はページソースを汚す余計な記述となってしまうこともあります。
テンプレートXMLで使われているb:ifなどのBlogger独自のタグについて知りたい場合はリンク先の記事を参考にしていただければと思います。
ミニマムなテンプレートXMLの作成
まずは既存のテーマのテンプレートXMLを加工して、Bloggerで表示できる最小限のテンプレートXMLを作成します。
ミニマムな状態から肉付けをすることで、余計な記述や処理のない軽量なページを作れます。
Bloggerのメニューから「テーマ」を選択し、カスタマイズの右側のタブから「バックアップ」を選択するとテンプレートXMLをダウンロードできます。
ダウンロードの前に、BloggerのUIのレイアウトから自分に不要なガジェットは消しておく(必要なものがあれば加えておく)と以後の作業が楽です。
ダウンロードが終わったらXMLを編集していきます。この時、Visual Studio Code(無料)などのコードエディタがあると作業がはかどります。
テンプレートXMLの中身
b:やmacro:などで始まっているタグはBloggerの処理命令です。またdata:となっている箇所ではページ構成処理時にデータを当てはめる場所になっています。このdataはガジェットにより使うことができる種類が変わってきます。詳しくはBloggerヘルプ:「レイアウト用のデータタグ」に掲載されています。
この中のb:sectionで囲まれている部分がBloggerのレイアウトの区切りとなり、b:wedgetがガジェットの区切りになります。
b:includableがプログラム上の「関数」に相当し、b:includeはそれを呼び出す処理をしています。
b:wedget(ガジェット)内にはidの属性値が「main」となっているb:includableが必ずひとつ存在し、処理はそこから始まります。
テンプレートXMLの中身を図式化するとおおむね次のようになっています。
idが関数名として扱われます。idがmainとなっているincludable(最初に呼び出されるメイン関数)がガジェット毎に必ず1つあります。
関数の呼び出しにはb:inculdeタグが使われます。name属性で呼び出す関数名(b:includableのid)を指定しています。
id=main以外のincludableの有無は任意です。
...
...
条件分岐を示すb:ifタグやループ構造を作るb:loopタグ、data:はb:sectionタグの外側にも存在できます。デフォルトだとheadで「all-head-content」という、記述のない関数の呼び出しがありますが、これはBloggerのシステムにビルドインされている関数だそうです。
サンプルテンプレート
筆者が作成した「ヘッダー」と「ブログの投稿」だけ残したサンプルは次のようになっています。
b:skinタグはないと動かせないので中身を空にして残しています。同様に消しても復活してくるb:includableも処理の中身を消しています。
headやbodyを閉じる部分で「<!-」としているのは、テンプレートXMLからHTMLを出力する際に、headやbodyタグの出力を契機に自動付与されるJavaScriptをまとめてコメントアウトするためです。この時、必要なタグ自身もコメントアウトに巻き込まれるので、別途出力する記述をしています。
blank.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html b:version='2' class='v2' expr:dir='data:blog.languageDirection' expr:lang='data:blog.locale' xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' xmlns:data='http://www.google.com/2005/gml/data' xmlns:expr='http://www.google.com/2005/gml/expr'>
<!-- head出力時に一緒に出力されるJSをエスケープ -->
<!--<head>-->
<!-- エスケープに巻き込まれたheadタグを出力 -->
<head>
<meta charset='utf-8'/>
<meta content='width=device-width,minimum-scale=1,initial-scale=1' name='viewport'/>
<b:include data='blog' name='all-head-content'/>
<title><data:blog.pageTitle/></title>
<b:skin><![CDATA[]]></b:skin>
<!--</head>-->
</head>
<body>
<b:section id='section-header'>
<b:widget id='Header1' locked='true' title='ヘッダー' type='Header' version='1'>
<b:widget-settings>
<b:widget-setting name='displayUrl'></b:widget-setting>
<b:widget-setting name='displayHeight'>260</b:widget-setting>
<b:widget-setting name='sectionWidth'>719</b:widget-setting>
<b:widget-setting name='useImage'>true</b:widget-setting>
<b:widget-setting name='shrinkToFit'>false</b:widget-setting>
<b:widget-setting name='imagePlacement'>BEHIND</b:widget-setting>
<b:widget-setting name='displayWidth'>1576</b:widget-setting>
</b:widget-settings>
<b:includable id='main'>
<div>タイトル</div>
</b:includable>
<b:includable id='description'/>
<b:includable id='title'/>
</b:widget>
</b:section>
<b:section id='section-main'>
<b:widget id='Blog1' locked='false' title='ブログの投稿' type='Blog' version='1'>
<b:widget-settings>
<b:widget-setting name='showDateHeader'>true</b:widget-setting>
<b:widget-setting name='style.textcolor'>#000000</b:widget-setting>
<b:widget-setting name='showShareButtons'>false</b:widget-setting>
<b:widget-setting name='authorLabel'>By</b:widget-setting>
<b:widget-setting name='showCommentLink'>false</b:widget-setting>
<b:widget-setting name='style.urlcolor'>#008000</b:widget-setting>
<b:widget-setting name='showAuthor'>false</b:widget-setting>
<b:widget-setting name='disableGooglePlusShare'>true</b:widget-setting>
<b:widget-setting name='style.linkcolor'>#0000ff</b:widget-setting>
<b:widget-setting name='style.unittype'>TextAndImage</b:widget-setting>
<b:widget-setting name='style.bgcolor'>#ffffff</b:widget-setting>
<b:widget-setting name='reactionsLabel'/>
<b:widget-setting name='showAuthorProfile'>false</b:widget-setting>
<b:widget-setting name='style.layout'>1x1</b:widget-setting>
<b:widget-setting name='showLabels'>false</b:widget-setting>
<b:widget-setting name='showLocation'>false</b:widget-setting>
<b:widget-setting name='showTimestamp'>false</b:widget-setting>
<b:widget-setting name='postsPerAd'>1</b:widget-setting>
<b:widget-setting name='showBacklinks'>false</b:widget-setting>
<b:widget-setting name='style.bordercolor'>#ffffff</b:widget-setting>
<b:widget-setting name='showInlineAds'>false</b:widget-setting>
<b:widget-setting name='showReactions'>false</b:widget-setting>
</b:widget-settings>
<b:includable id='main' var='top'>
<!-- 投稿かページなら -->
<b:if cond='data:blog.pageType in {"static_page", "item"}'>
<b:loop values='data:posts' var='post'>
<!-- 複数ページがありループで戻ってきていたら、divタグを閉じる -->
<b:if cond='data:post.isDateStart and not data:post.isFirstPost'>
<!-- 閉じタグをそのまま書くと、コードチェックにひっかっかるのでエスケープ -->
</div></div>
</b:if>
<b:if cond='data:post.isDateStart'>
<div class="date-outer">
</b:if>
<b:if cond='data:post.dateHeader'>
<h2 class='date-header'><data:post.dateHeader/></h2>
</b:if>
<b:if cond='data:post.isDateStart'>
<div class="date-posts">
</b:if>
<div class='post-outer'>
<b:include data='post' name='post'/>
</div>
</b:loop>
<b:if cond='data:numPosts != 0'>
</div></div>
</b:if>
<!-- 次へ・前へ(必要ならincludableも復元して下さい)
<b:include name='nextprev'/>
-->
<b:else/>
<!-- 投稿かページ以外 -->
<b:if cond='data:blog.homepageUrl == data:blog.url'>
<div>トップページコンテンツ</div>
<b:else/>
<!-- 検索やラベルなどのサマリ表示呼び出し -->
<b:include data='posts' name='disppostsummary'/>
<!-- 次へ・前へ(必要ならincludableも復元して下さい)
<b:include name='nextprev'/>
-->
</b:if>
</b:if>
</b:includable>
<b:includable id='backlinkDeleteIcon' var='backlink'/>
<b:includable id='backlinks' var='post'/>
<b:includable id='comment-form' var='post'/>
<b:includable id='commentDeleteIcon' var='comment'/>
<b:includable id='comment_count_picker' var='post'/>
<b:includable id='comment_picker' var='post'/>
<b:includable id='comments' var='post'/>
<b:includable id='disppostsummary' var='posts'>
<!-- 検索やラベルなどのサマリ表示の本体 -->
<b:loop values='data:posts' var='post'>
<div>
<div style='float:left; margin-right:1em;'>
<a expr:href='data:post.url'><img alt='' expr:src='data:post.thumbnailUrl' height='72' loading='lazy' width='72'/></a>
</div>
<div><a expr:href='data:post.url'><data:post.title/></a></div>
<div>
<data:post.snippet/>
</div>
<hr style='clear:both;'/>
</div>
</b:loop>
</b:includable>
<b:includable id='feedLinks'/>
<b:includable id='feedLinksBody' var='links'/>
<b:includable id='iframe_comments' var='post'/>
<b:includable id='mobile-index-post' var='post'/>
<b:includable id='mobile-main' var='top'/>
<b:includable id='mobile-nextprev'/>
<b:includable id='mobile-post' var='post'/>
<b:includable id='nextprev'/>
<b:includable id='post' var='post'>
<!-- 投稿・ページ出力本体 -->
<main>
<b:if cond='data:post.title'>
<h1 class='post-title'>
<b:if cond='data:post.link or (data:post.url and data:blog.url != data:post.url)'>
<a expr:href='data:post.link ? data:post.link : data:post.url'><data:post.title/></a>
<b:else/>
<data:post.title/>
</b:if>
</h1>
</b:if>
<data:post.body/>
</main>
</b:includable>
<b:includable id='postQuickEdit' var='post'/>
<b:includable id='shareButtons' var='post'/>
<b:includable id='status-message'/>
<b:includable id='threaded-comment-form' var='post'/>
<b:includable id='threaded_comment_js' var='post'/>
<b:includable id='threaded_comments' var='post'/>
</b:widget>
</b:section>
<!--</body>--></body>
</html>
テンプレートXML上でコメントアウトすると、表示されるページソースにはその部分は出力されないことがありました。発生条件も不明で、バクなのか仕様なのかわかりませんが、コメントアウトした部分をページに出力したい場合は先ほど同様に「<!-」という記述を使います。
2022/01追記
headを閉じる場所(/head)をコメントアウトした状態で、BloggerのメニューからAdSense連携をONにすると、意図したように機能しません。
headを閉じる過程でbolggerがHTMLのコメントを出力するのが原因で、HTMLではコメントの多重化は許可されていないため、自動出力のコメント閉じタグでコメントが終わってしまうのが原因です。
そこで筆者は、templateで囲って次のように/headタグを修正しました。template内にheadがあることは既に構造的にはおかしいのですが、少しでも改善するためにtemplate内でhead開始タグを追加して、タグのバランスを保つようにしています。
templateなのでチェックはされますが、レンダリングされません。
<template&gt;<head></head></template&gt; </head>
また、筆者がblogger立上げた時からお世話になっている「バグ取りの日々」というサイトでもBloggerの空のテンプレートを作る方法を紹介しているようです。こちらを参考にしてhtmlにb:js=falseを加えることで、/headがある状態での軽量化ができました。ありがとうございました。そちらのページでは筆者の方法とはまた違った方法で、/headの問題も解決しているようなので、よろしかったらそちらのページも参考にしてみてください。