テンプレートタグ
sinonome のテンプレートタグ(以下「テンプレートタグ」)は、記法的にはHTMLに類似しています。
ただし、HTMLタグは基本的には文書構造を記述する一方、テンプレートタグは以下のような様々な機能を持ちます。
- コードを変数として格納したり、呼び出したりする
- ブログ記事やウェブページを、繰り返し出力する
- ブログ記事やウェブページの情報を呼び出す
- 条件によって異なる内容を出力したり、異なる処理を行ったりする
また、HTMLタグは<tag>あるいは<tag>~</tag>という形式で入力しますが、テンプレートタグは、{tag}あるいは{tag}~{/tag}という形式で入力します。
以下は、各テンプレートタグの解説です。
範囲タグとインラインタグで分け、それぞれ汎用→記事→ページ→アーカイブ→タグ→そのほか、とゆるく分けて並べてあります。
範囲タグ
{tag}~{/tag}という形式で、範囲を囲むタグです。
ignore
このタグで囲んだ領域は無視されます。
if
指定した条件が真の場合に処理します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| name | 変数名を指定します。 | |
| eq | name がこの値の場合、処理を行います。 | |
| ne | name がこの値でない場合、処理を行います。 |
else
if タグの領域の中に書き、ifタグで指定された条件が偽の場合に処理します。
(例)設定した変数「ページタイトル」の値が「トップページ」の場合とそうでない場合とで、titleタグの内容を変化させる
{if name="ページタイトル" eq="トップページ"}
<title>サイトタイトル - サイトの概要</title>
{else}
<title>{getvar name="ページタイトル"} | サイトタイトル</title>
{/if}
なおelseタグは、ifタグだけでなく、他のタグの中でも書く場合があります。
詳しくはそれぞれのタグの説明をご参照ください。
entries
記事のデータを出力するループ(記事ループ)です。
このループの中に各種タグを記述することで、順番に記事のデータを取り出すことができます。
どのように出力するかは、アーカイブテンプレートに応じて自動で設定されますが、モディファイアで指定することもできます。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| index | 指定したindexの記事のみを出力します。 | |
| offset | ループのはじまりのindex値を指定します。 | 0 |
| limit | 上限を指定します。 | 9999 |
| tag | 指定したタグIDの記事のみを出力します。 | 指定なし(全ての記事ファイルが対象) |
entrynext
次の記事を出力します。
elseタグで、次の記事が存在しない場合の出力も書けます。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| scope | 範囲を指定します。 tag: 範囲を同一タグ内に限定します。タグが複数付与されている場合は、最初に付与されているタグが対象になります。 all: 全ての記事ファイルを範囲とします。(デフォルト) |
all |
{entrynext}
{entrytitle}<!--次の記事のタイトル-->
{else}
次の記事はありません
{/entrynext}
entryprev
前の記事を出力します。
モディファイア等はentrynextと同様です。
pages
ページのデータを出力するループ(ページループ)です。
このループの中に各種タグを記述することで、順番にページのデータを取り出すことができます。
どのように出力するかは、アーカイブテンプレートに応じて自動で設定されますが、モディファイアで指定することもできます。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| index | 指定したindexの記事のみを出力します。 | |
| offset | ループのはじまりのindex値を指定します。 | 0 |
| limit | 上限を指定します。 | 9999 |
| file | ページファイルのファイル名を指定します。拡張子は必要ありません。 | 指定なし(全てのページファイルが対象) |
pagenext
次のページを出力します。
モディファイア等はentrynextと同様です。
pageprev
前のページを出力します。
モディファイア等はentrynextと同様です。
archives
アーカイブのデータを出力するループ(アーカイブループ)です。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| offset | ループのはじまりのindex値を指定します。 | 0 |
| limit | 上限を指定します。 | 9999 |
| archive_type | アーカイブのタイプを指定します。 tagarchive: タグ別のアーカイブ ※entryarchiveの指定は対応していません |
(例)タグ別アーカイブページのリンク一覧を表示
<ul>
{archives archive_type="tagarchive"}
<li><a href="{archivelink}">{archivetitle}</a></li>
{/archives}
</ul>
tags
記事に付けたタグを出力するループ(タグループ)です。
このループの中に各種タグを記述することで、順番にタグのデータを取り出すことができます。
loop
変数に格納した配列の各要素に順番にアクセスするループです。
配列の使用方法については別に解説します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| name | 配列が格納された変数名を指定します。 | |
| glue | 要素と要素の間に出力する内容を指定します。 | |
| reverse | 1を指定すると、後ろから前に向かってアクセスします。 | |
| limit | ループの上限回数を指定します。 |
なお、ループの中のコードについて、__index__と書かれた部分が、ループの回数に置き換わります。
普通に数字を出力もできますが、getvar タグによる序数付きでの値の取り出しにも使います。
(例)「変数名」に格納された配列の値を順番に取り出して表示
{setvar name="変数名[]" value="あ"}
{setvar name="変数名[]" value="い"}
{setvar name="変数名[]" value="う"}
{setvar name="変数名[]" value="え"}
{loop name="変数名" glue="・" reverse="1" limit="3" }
{getvar name="変数名[__index__]"}
{/loop}
「え・う・い」と表示されます。
reverse="1"なので逆順に取り出され、limit="3"なので4つ目の「あ」は出力されません。
setvarblock
変数に、囲んだ内容を格納します。
格納前に、内容が解釈されます。
{setvarblock name="変数"}
{blogtitle}
{/setvarblock}
ブログ名が「サンプルブログ」の場合、「変数」には「サンプルブログ」が格納されます。
ひとつの変数に、複数のデータを、配列として格納することもできます。
変数名の直後に[]を書いてください。
{setvarblock name="ひらがな[]"}あ{/setvarblock}
{setvarblock name="ひらがな[]"}い{/setvarblock}
{setvarblock name="ひらがな[]"}う{/setvarblock}
変数「ひらがな」の0番目に「あ」、1番目に「い」、2番目に「う」が格納されます。
配列のデータの取り出しは、以下のように行います。
{getvar name="ひらがな[1]"}
「い」が取り出されます。
setvartemplateとsetvarも、同様の方法で配列を格納できます。
setvartemplate
変数に、囲んだ内容を格納します。
ただしsetvarblockと異なり、内容は解釈せず、コードをそのまま格納します。
タグ名が示す通り、テンプレートの一部を変数に格納し、複数の箇所から呼び出して使うのが主な用途となります。
{setvartemplate name"記事本文のコード"}
<h2>{entrytitle}</h2>
<div class="honbun">
{entrybody}
{entrymore}
</div>
{/setvartemplate}
インラインタグ
blogname
ブログ名を表示します。
blogdescription
ブログの概要を表示します。
blogauthor
ブログの作者を表示します。
blogurl
ブログのURLを表示します。
entrytitle
記事のタイトルを表示します。
entrybody
記事の本文を表示します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| headinglevel | 一番上の見出しレベルを指定します。 最も上のレベルの見出しから順に heading1~heading6というクラスが付与されます。クラス付与が必要ない場合は、 noclassオプションを指定します。 |
2 |
sinonomeでは、本文中の一番上の見出しレベルは2、つまり##となります。
(#は記事のタイトルとして使用するため、本文では使いません)
通常、Markdownでは、##を<h2>タグとして出力します。
しかしheadinglevelを指定することで、これを<h1>~<h6>のどれかに変えられます。
同時に、CSS設定に利用できるクラス名を付与します。
例えば、以下のような記事の本文があるとします。
## シャープ記号2つの見出し
### シャープ記号3つの見出し1
### シャープ記号3つの見出し2
#### シャープ記号4つの見出し
そして、テンプレートが以下のようになっているとします。
<!-- トップページ -->
<h1>サイトのタイトル</h1>
<h2>最新記事</h2>
{entries limit="1"}
<h3>{entrytitle}</h3>
{entrybody headinglevel="4"}
{/entries}
すると、次のような出力になります。
<!-- トップページ -->
<h1>サイトのタイトル</h1>
<h2>最新記事</h2>
<h3>記事タイトル</h3>
<h4 class="heading1">シャープ記号2つの見出し</h4>
<h5 class="heading2">シャープ記号3つの見出し1</h5>
<h5 class="heading2">シャープ記号3つの見出し2</h5>
<h6 class="heading3">シャープ記号4つの見出し</h6>
headinglevelを4に設定したため、##による見出しが<h2>ではなく、<h4>で出力されます。
また、一番上のレベルの見出しにはheading1、その次のレベルの見出しにはheading2…というふうにクラスが付与されます。
この仕組みにより、ユーザーはテンプレートによって適切な見出しレベルを意識することなく、本文の#記号は2つから始める、という原則通りに記事を書けるようになります。
テーマ開発者は上記を保証するため、当タグを用いる際にはheadinglevel属性(とCSS)を適切に設定する必要があります。
なおv0.0.16より、見出しレベル指定と同時にnoclassを指定することで、クラスの付与を省略できます。
{entries limit="1"}
{entrybody headinglevel="4,noclass"}
{/entries}
<h4>シャープ記号2つの見出し</h4>
..
entrymore
記事の本文の続きを表示します。
使用可能なモディファイアはentrybodyと同様です。
entrydate
記事の日付を表示します。
DATEに記載した内容が表示されます。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| format | フォーマットを指定します。 | %Y-%m-%d %H:%M:%S |
DATEの値として許容されるのは、以下の形式のみです。
DATEが以下以外の形式で書かれている場合、またはDATEが書かれていない場合は、出力した時点の年月日・時刻が使用されます。
| 形式 | 例 | 備考 |
|---|---|---|
| 西暦4桁-月2桁-日2桁 時2桁:分2桁:秒2桁 | 2020-04-15 23:12:06 | |
| 西暦4桁-月2桁-日2桁 | 2020-04-15 | 時刻部分は「00:00:00」と見なされます |
例えばある投稿のDATEの値が 2020-09-28 なら、以下のコードは「2020年09月28日 00時00分00秒」を出力します。
{pagedate format="%Y年%m月%d日 %H時%M分%S秒 "}
フォーマットには以下の記法が使用できます。
| 記法 | 意味 | 実装状況(記載なしは実装済み) |
|---|---|---|
| %Y | 年を4桁 | |
| %y | 年を2桁 | ●未実装 |
| %b | 月を省略形式で | |
| %B | 月を完全形式で | |
| %m | 月を2桁 | |
| %d | 日を2桁 | |
| %e | 日を2桁 空白パディング | |
| %j | 年初からの日を、3桁の数字で表示します。 1桁、2桁の場合は、0が付加されます。(例: 078) |
●未実装 |
| %H | 時を24hの2桁 0パディング | |
| %k | 時を24hの2桁 空白パディング | |
| %I | 時を12hの2桁 0パディング | |
| %l | 時を12hの2桁 空白パディング | |
| %M | 分を2桁 0パディング | |
| %S | 秒を2桁 0パディング | |
| %p | AM PM | |
| %a | 曜日 省略形式 | |
| %A | 曜日 完全形式 | |
| %w | 曜日 完全形式 | |
| %x | 言語に合わせて日付を表示 ほとんどの言語では %B %d, %Y と同じ (例: September 06, 2002、2002年09月06日) |
|
| %X | 言語に合わせて時刻を表示 ほとんどの言語では %I:%M %p と同じ (例: 04:31 PM、16:31) |
entryfield
記事のメタ情報を表示します。
メタ情報の領域には好きな情報を入れることができますので、それらを取り出す場合に使用します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| name | メタ情報の名前を指定します。 |
# クリスマス(2020年)
<!--
ENGLISH_TITLE: CHRISTMAS 2020
-->
本文…
{entryfield name="ENGLISH_TITLE"}
例えば記事の日本語タイトルの下に、飾りとして英字を入れたいというケースがあるとします。
その場合、メタ情報領域にENGLISH_TITLE:で始まる行を書き、上記のタグを呼び出す、といった風に使えます。
entrylink
記事のURLを表示します。
entrybasename
記事の OUTPUTPATH を表示します。
pagetitle
ページのタイトルを表示します。
pagebody
ページの本文を表示します。
pagemore
ページの続き部分を表示します。
pagedate
ページの日付を表示します。
詳細はentrydateと同じです。
pagefield
ページのメタ情報を表示します。
詳細はentryfieldと同じです。
pagelink
ページのURLを表示します。
pagebasename
ページの OUTPUTPATH を表示します。
pagefiletitle
ページファイルのタイトルを表示します。
ページファイルのヘッダーに記入された TITLE の内容が呼び出されます。
ページファイルのヘッダーは、ファイルの冒頭に置いた<!-- ~ -->内に記述します。
<!--
TITLE: ページファイルのタイトル
-->
# ページ1
<!--
OUTPUTPATH: page1
-->
ページ1の本文…
# ページ2
<!--
OUTPUTPATH: page2
-->
ページ2の本文…
archivetitle
アーカイブファイルに指定したタイトルを表示します。
archivelink
アーカイブページのURLを表示します。
archivedescription
アーカイブの概要を表示します。
現在のところ、タグアーカイブの場合のにみ有効です(タグの概要を表示)。
archivepager
アーカイブページがページで区切られている時、各ページへのリンクを表示します。
以下のようなHTMLが表示されます。
<ul>
<li><a href="ページ1のURL">1</a></li>
<li><a href="ページ2のURL">2</a></li>
<li><a href="ページ3のURL">3</a></li>
</ul>
archivepagenum
アーカイブページがページで区切られている時、ページの番号を表示します。
archivepagetotal
アーカイブページがページで区切られている時、ページの総数を表示します。
tagname
タグの名前を表示します。
tagid
タグのタグIDを表示します。
taglink
タグアーカイブへのリンクを表示します。
tagdescription
タグの概要を表示します。
include
modules.htmlに記述した各モジュールを呼び出します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| module | モジュールの名前を指定します。(TITLEに指定した名前) |
setvar
変数を格納します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| name | 変数名を指定します。 | |
| value | 格納する値を指定します。 |
getvar
変数の内容を表示します。
| モディファイア | 概要 | デフォルト値 |
|---|---|---|
| name | 変数名を指定します。 |
特殊なタグ
以下は、テンプレートだけではなく、記事本文やウェブページ本文でも使うことのできるタグです。
root
トップページディレクトリへの相対パスを表示します。
出力されるページによって、相対パスは変化します。
トップページにリンクしたい場合、単に
<a href="index.html">トップ</a>
と書くと、
(1) index.htmlと同じ階層にあるページ ならOKですが、
(2) サブディレクトリ\subの中にあるページ ではリンク切れになります。
そこで、以下のように記述します。
<a href="{root}index.html">トップ</a>
{root}は、「出力されるページから見た、トップページディレクトリへの相対パス」に置き換わります。
つまり、(1)では空文字列、(2)では「../」に置き換わりますので、リンク切れが発生しません。
画像についても同じです。
例えば、\files\logo.png を表示するために以下を書きます。
<img src="{root}logo.png" alt="ロゴ">
ページが \sub\sub2\sub3\sub4\sub5 に生成された場合は、コードは以下のように出力されます。
<img src="../../../../../files/logo.png" alt="ロゴ">
タグそのものを書きたい場合
記事やウェブページ上にも書けるタグについて、(例えばこの文書のように)そのものを書きたい場合は、タグの開始・終了記号{}を実体参照で記述してください。
また実体参照での記述に問題がある場合は、開始記号と終了記号を二重にしてください。出力の直前に一つ分に置換されます。
../ ← {root} 普通に記述
{root} ← {root} 実体参照で記述
{root} ← {{root}} 開始記号と終了記号で二重に囲む
グローバルモディファイア
全てのタグに使用できるモディファイアです。
trim
文字列の前後の空白文字を削除します。
{setvar name="テキスト" value=" TEST " }
{getvar name="テキスト" trim="1" }
両端に空白のない「TEST」と表示されます。
replace
指定した文字列を全て、指定した文字列に置き換えます。対象の文字列と置き換えた後の文字列をカンマで区切って入力します。
必要であれば、2回以上書くこともできます。
{setvar name="テキスト" value="TEST" }
{getvar name="テキスト" replace="T,W" }
{setvar name="テキスト2" value="NORTH" }
{getvar name="テキスト2" replace="N,S" replace="R,U" }
上は「WESW」と表示され、下は「SOUTH」と表示されます。
remove_html
HTMLタグを取り除きます。
正確には、実在するタグかどうかの検証は行わず、< と > で囲まれた部分を全て削除します。
{setvar name="テキスト" value="<strong>TEST</strong>" }
{getvar name="テキスト" remove_html="1" }
strongタグが取り除かれますので、通常の文字の太さで「TEST」と表示されるでしょう。
strform
出力内容がある場合に、出力内容を書式化します。
{setvar name="テキスト" value="NEW" }
{getvar name="テキスト" strform="<strong>%s</strong>" }
{setvar name="テキスト2" value="" }
{getvar name="テキスト2" strform="<strong>%s</strong>" }
変数「テキスト」をgetvarしている上の方は、<strong>NEW</strong>と出力されます。
変数「テキスト2」をgetvarしている下の方は、出力内容がないのでstrformは適用されず、したがって単に空文字列が出力されます。
Tips
モディファイアの値には変数を使用できます。
値の頭に「$」をつけると、その変数の値が参照されます。
{tags}
{setvarblock name="タグのID"}{tagid}{/setvarblock}
<h2>{tagname}</h2>
<ul>
{entries tag="$タグのID" limit="3"}
<li><a href="{entrylink}">{entrytitle}</a></li>
{/entries}
</ul>
{/tags}
全てのタグごとに、記事一覧(最大3記事まで)を表示する例です。
{tagid}の値を「タグのID」という変数に入れ、{entries}のtagモディファイアの値として使用しています。
ToDo
sinonome の現状について
sinonome は現在、アルファバージョンかそれ以前の段階であり、常用はおすすめしません。
例えば、今後以下のような互換性がない変更を予定しています。
- ディレクトリ構造の変更(プロファイル的に扱う)
- 出力ファイル名を指定していない場合の動作の仕様変更
いつ頃ベータ版になるかは今のところ未定です。
今後の改良点など
以下、作者が今後対応したいと考えている事項等を列挙します。
大量に列挙していましたが、2022年6月に整理しました。
pages の file 指定は前方一致もあったほうがいい(?)
ifタグのeqは完全一致だが、前方一致もほしい(後方一致はいらない?)
ただいろいろ増やすよりは正規表現を使えるようにした方がいいかもしれない文字列をsplitして変数(の配列)に入れるのが欲しい
TITLEとかを階層的にして、SPLITして0番目の要素でコンテンツの種類を判定したりとかentrytitleとかのサニタイズ つまり<や>を実体参照にしたりとか
使われる箇所によって適切なサニタイズが異なると思われるのでグローバルモディファイアで実装する?
sanitize=“html” とか sanitize=“url” とか
仕様とするもの
- モディファイアの値を囲むのはダブルクォート「““」のみで、現状シングルクォート「''」は不可
絶対にシングルクォートにできないと困るというケースが思い浮かばない
クォートなしも許容するのか、という話になってしまうのでダブルクォート固定がいい
未検証
- インストールパスにUnicode文字があるとaya.dllがロードできない
具体的にはload時にカレントディレクトリを渡す時点でエラーになる
TAMAにDnDしてもロードできないのでAYAの仕様っぽい
ただこの件、確か大昔にも知っていて、でも何かを見て「あぁ、じゃあ仕方ない(あるいは対応する意味ないっぽい)」と思った気がする(もしかしたらだけどMATERIAがUnicodeなパスの取り扱いできないとかそういう感じの件だったかも)
→実際確認して、MATERIAやSSPではUnicodeパスで起動しないのを確認した つまりAYAのこの仕様も仕方ないというレベル
そもそもユーザー層を考えると、Unicodeが含まれるパスで使うということ自体あまりないはずなので仕様ということにする
使用ライブラリ等
以下のライブラリを使用しました。
- fpc-markdown: Markdown Processor for FPC
https://github.com/luridarmawan/fpc-markdown - YAYA(Yet another AYA)
http://ms.shillest.net
https://github.com/ponapalt/yaya-shiori
上記 YAYA は AYA をもとに作成されています。
AYAのその作者さんについて、詳細はこの記事で述べた通りです。
- AYA(文字列加工ライブラリ)
http://umeici.onjn.jp