🛠️

a-blog cms を利用して静的HTMLサイトからCMSのテーマを作ってみよう 2022年版 その3「モジュール編」

2022/05/26に公開

今回は、a-blog cms のモジュールを中心に解説を行っていきます。

https://zenn.dev/kazumich/articles/1bd5c2e8a23afb

の続編になりますので、その2「カスタムフィールド編」がまだの方は合わせてご覧ください。

タイトルタグを動的に変更する

現在、<head> 内の <title> 〜 </title> について初期状態のままですので、この部分も自動で編集されるように実装を進めます。

エントリータイトル | カテゴリー名 | ブログ名

タイトルタグについては、OGPモジュールというモジュールが用意されておりますので、タイトルタグに加え、<meta>部分もこれで対応が可能です。

OGPモジュールスニペット
<!-- BEGIN_MODULE Ogp -->
<title>{title}</title>
<meta property="og:url" content="%{PERMALINK}">
<meta property="og:site_name" content="%{ROOT_BLOG_NAME}">
<meta property="og:title" content="{title}">
<meta property="og:type" content="{type}">
<!-- BEGIN_IF [{description}[delnl]/nem/] -->
<meta property="og:description" content="{description}[mb_trim(350, '...')|delnl|escape]"><!-- END_IF --><!-- BEGIN_IF [{image}/nem/] -->
<!-- BEGIN_IF [{image@type}/eq/media] -->
<meta property="og:image" content="http://localhost/media/{image}">
<meta property="og:image:secure_url" content="http://localhost/media/{image}" />
<!-- ELSE -->
<meta property="og:image" content="http://localhost/archives/{image}">
<meta property="og:image:secure_url" content="http://localhost/archives/{image}" />
<!-- END_IF -->
<meta property="og:image:width" content="{image@x}" />
<meta property="og:image:height" content="{image@y}" /><!-- END_IF --><!-- BEGIN_IF [{description}[delnl]/nem/] -->
<meta name="description" content="{description}[mb_trim(350, '...')|delnl|escape]"><!-- END_IF --><!-- BEGIN_IF [{keywords}/nem/] -->
<meta name="keywords" content="{keywords}"><!-- END_IF -->
<!-- END_MODULE Ogp -->

このスニペットでもいいのですが、beginnerテーマの中に用意されている /themes/beginner/include/head/meta.html を利用した方が Twitterカードについても対応されているのでオススメかもしれません。

sampleフォルダーに includeフォルダーを作成し、その中に headフォルダーを作り、meta.html ファイルをコピーしてきます。

index.html , list.html , entry.html の <title> <meta> を削除して

@include("/include/head/meta.html")

に置き換えます。このインクルード機能について説明ができていませんので、次でしっかり説明をします。

インクルード機能でファイルをまとめる

テンプレートの HTML の中で、別の HTML を読み込む機能をインクルード機能と呼びます。

一般的に、ヘッダー部分やフッター部分については、どのページでも同様なことが多いので、 header.html や footer.html のようなファイルを用意し各ファイルからインクルードします。 フォルダー名の決まりはありませんが、include にまとめるのが a-blog cms の一般的なルールになっています。

@include("/include/header.html")
	
@include("/include/footer.html")

さらに、インストール時に最初から用意されている beginnerテーマを参考に紹介しておきますが、基本はモジュール単位でファイル分けインクルードするようにしています。

<!DOCTYPE html>
<html class="no-js" lang="ja">
<head>
  @include("/include/head/meta.html")
  @include("/include/head/link.html")
  @include("/include/head/js.html")
</head>
<body>
<!-- ヘッダー -->
@include("/include/header.html")
<div class="acms-container js-pretty-scroll-container">
  <!-- ※管理用パーツ -->
  @include("/admin/action.html")
  @include("/include/header/top-image.html")
  <div class="acms-grid">
    <main class="acms-col-lg-9 main">
      <div class="main-inner is-space-right">
        <!-- エントリーヘッドライン(トップ用) -->
        @include("/include/entry/headline-top.html")
        <!-- エントリーサマリー -->
        @include("/include/entry/summary-top.html")
        <!-- 確認用テンプレート --> 
        @include("/include/check-seo.html")
      </div>
    </main>
    <div class="acms-col-lg-3 side">
      <div class="js-pretty-scroll">
        <!-- 検索フォーム -->
        @include("/include/parts/search.html")
        <!-- ピックアップリスト -->
        @include("/include/entry/summary-pickup.html")
        <!-- バナー -->
        @include("/include/siteparts/banner.html")
        <!-- リンクリスト -->
        @include("/include/siteparts/link-list.html")
        <!-- モバイル:ナビゲーションメニュー -->
        @include("/include/parts/mobile-nav.html")
        <!-- ログインボタン -->
        @include("/include/parts/login-button.html")
      </div>
    </div>
  </div>
</div>
<!-- お問い合わせ -->
@include("/include/footer/suggest.html")
<!-- フッター -->
@include("/include/footer.html")
</body>
</html>

グローバルナビゲーションの実装

ナビゲーションは index.html , list.html , entry.html どのページにもあります。この段階では、インクルード機能でしっかりファイル分けができているようであれば、1つのファイルのみ修正すればいい事になっています。

<div class="header-nav">
  <div class="acms-grid">
    <nav class="navbar">
      <ul>
        <li><a href="index.html">ホーム</a></li>
        <li class="stay"><a href="list.html">一覧</a></li>
        <li><a href="entry.html">詳細</a></li>
      </ul>
    </nav>
  </div>
</div>

<div class="header-nav"> の辺りを Navigation に置き換えていきます。 Navigation モジュールは、<ul><li> で書かれていますが、入れ子構造にできる仕様になっており、それを1つの <!-- BEGIN navigation:loop --> 〜 <!-- END navigation:loop --> で作られているので制御用のブロックが多く分かりにくいです。

Navigationスニペット
<!-- BEGIN_MODULE Navigation -->
<div>
  @include("/admin/module/setting.html")
  <div class="acms-navbar acms-margin-bottom-medium clearfix">
  <!-- BEGIN navigation:loop -->
    <!-- BEGIN ul#front --><ul><!-- END ul#front -->
      <!-- BEGIN li#front --><li {attr} class="c_{level}" ><!-- END li#front -->
        <!-- BEGIN link#front --><a href="{url}" {attr} target="{target}"><!-- END link#front -->
        <!-- BEGIN label:veil -->{label}[raw]<!-- END label:veil -->
        <!-- BEGIN link#rear --></a><!-- END link#rear -->
      <!-- BEGIN li#rear --></li><!-- END li#rear -->
    <!-- BEGIN ul#rear --></ul><!-- END ul#rear -->
  <!-- END navigation:loop -->
  </div>
</div>
<!-- END_MODULE Navigation -->

<nav class="navbar"> の中にある <ul> 〜 </ul> を <!-- BEGIN navigation:loop --> 〜 <!-- END navigation:loop --> に置き換えるような感じで実装を進めてください。

最終的には、以下のようになります。もちろんモジュールIDの設定 id="nav_global" も忘れずに行ってください。

<!-- BEGIN_MODULE Navigation id="nav_global" -->
<div class="header-nav">
  <div class="acms-grid">
    <nav class="navbar">
  <!-- BEGIN navigation:loop -->
    <!-- BEGIN ul#front --><ul><!-- END ul#front -->
    <!-- BEGIN li#front --><li {attr} class="c_{level}" ><!-- END li#front -->
      <!-- BEGIN link#front --><a href="{url}" {attr} target="{target}"><!-- END link#front -->
      <!-- BEGIN label:veil -->{label}[raw]<!-- END label:veil -->
      <!-- BEGIN link#rear --></a><!-- END link#rear -->
    <!-- BEGIN li#rear --></li><!-- END li#rear -->
    <!-- BEGIN ul#rear --></ul><!-- END ul#rear -->
  <!-- END navigation:loop -->
    </nav>
  </div>
</div>
<!-- END_MODULE Navigation -->

モジュールIDの条件設定しか行っていない人は、何も表示されずに焦った人もいることでしょう。表示設定側を以下のように行ってください。

画像だとコピぺできないので、表にも書いておきます。

ラベル URL 属性
HOME %{HOME_URL} class="js-link_match_location-full"
会社概要 %{HOME_URL}company/ class="js-link_match_location"
物件情報 %{HOME_URL}realestate/ class="js-link_match_location"
お知らせ %{HOME_URL}news/ class="js-link_match_location"
採用情報 %{HOME_URL}recruit/ class="js-link_match_location"
お問い合せ %{HOME_URL}contact/ class="js-link_match_location"

class="js-link_match_location" について解説しておきます。

この class をつけておくと、そのディレクトリーを表示している時に class="stay" を JavaScript でつけてくれます。例えば、/news/ の時と /news/entry-11.html どちらでも今は「お知らせ」にいますを伝えるためです。

HOME だけは、少し違って class="js-link_match_location-full" と設定されているので完全一致している時という指定になります。

属性は <li> に設定したい class などを、子要素属性には <a> に追記したい class などを設定できるようになっています。

トップページのスライダーの画像を変更できるように実装

top.html のスライダー部分を探してみます。

<div class="module-section">
  <div class="js-slider">
    <div>
      <a href="list.html" target="_self" class="slider-item"><img src="/images/slider_zoo1.jpg" width="1150" height="400" alt="" class="acms-img-responsive slider-image" /></a>
    </div>
    <div>
      <a href="list.html" target="_self" class="slider-item"><img src="/images/slider_zoo2.jpg" width="1150" height="400" alt="" class="acms-img-responsive slider-image" /></a>
    </div>
    <div>
      <a href="list.html" target="_self" class="slider-item"><img src="/images/slider_zoo3.jpg" width="1150" height="400" alt="" class="acms-img-responsive slider-image" /></a>
    </div>
  </div>
</div>

スライダーは JavaScript で実装されており、上記のような HTML になっています。 class のついていない <div> 部分が3つ同じ構造になっているのが確認できます。

メディアバナーモジュールを利用して実装していきます。バナーというとサブカラムにある a-blog cms のロゴみたいなものを想像しますが、複数件の画像とリンクを管理できればどのようなモジュールでも大丈夫ではありますが、メディアバナーモジュールを利用するとバナーの表示期間の設定も活用できるので便利に使えるのではないでしょうか。

Media_Bannerスニペット
<!-- BEGIN_MODULE Media_Banner -->
<div>
@include("/admin/module/setting.html")
<ul class="acms-list-nostyle acms-grid">
  <!-- BEGIN banner:loop -->
  <li class="acms-col-md-4">
    <!-- BEGIN banner#src -->
    {src}[raw]
    <!-- END banner#src -->
    <!-- BEGIN banner#img -->
    <a href="{url}" target="{target}"><img src="%{MEDIA_ARCHIVES_DIR}{img}" width="{x}" height="{y}" class="acms-img-responsive" alt="{alt}" /></a>
    <!-- END banner#img -->
  </li>
  <!-- END banner:loop -->
</ul>
</div>
<!-- END_MODULE Media_Banner -->

元の HTML を挟むように <!-- BEGIN_MODULE Media_Banner --> 〜 <!-- END_MODULE Media_Banner --> を追記し、モジュールID id="top_image" を設定します。

<!-- BEGIN_MODULE Media_Banner id="top_image" -->
<div class="module-section">
  <div class="js-slider">
    <!-- <div>
      <a href="list.html" target="_self" class="slider-item"><img src="/images/slider_zoo1.jpg" width="1150" height="400" alt="" class="acms-img-responsive slider-image" /></a>
    </div> -->
    <!-- BEGIN banner:loop -->
    <div>
      <a href="{url}" target="_self" class="slider-item"><img src="%{MEDIA_ARCHIVES_DIR}{img}" width="{x}" height="{y}" alt="{alt}" class="acms-img-responsive slider-image" /></a>
    </div>
    <!-- END banner:loop -->
  </div>
</div>
<!-- END_MODULE Media_Banner -->

3つのループのうちの1つをコメントタグで囲み残しておき、2つ目の<div>をスニペットを参考に{変数}に置き換えていきます。3つ目の<div>は削除しました。

トピックパスを実装

トピックパス(パンくずリスト) は index.html には用意していませんが list.html , entry.html に用意されています。

list.html
<nav class="topicpath">
 <ol class="topicpath-list acms-container sp-container clearfix">
  <li class="topicpath-item"><a href="index.html" class="topicpath-link">HOME</a></li>
  <li class="topicpath-item"><a href="list.html" class="topicpath-link">カテゴリー名</a></li>
 </ol>
</nav>
entry.html
<nav class="topicpath">
 <ol class="topicpath-list acms-container sp-container clearfix">
  <li class="topicpath-item"><a href="index.html" class="topicpath-link">HOME</a></li>
  <li class="topicpath-item"><a href="list.html" class="topicpath-link">カテゴリー名</a></li>
  <li class="topicpath-item"><a href="entry.html" class="topicpath-link">エントリー名</a></li>
 </ol>
</nav>

この部分を、どちらも @include("/include/topicpath.html") として、topicpath.html を用意します。

Topicpathスニペット
<!-- BEGIN_MODULE Topicpath -->
<ol class="acms-topicpath acms-margin-bottom-mini clearfix">
 <!-- BEGIN blog:loop -->
 <li><a href="{url}">{name}</a></li><!-- END blog:loop --><!-- BEGIN category:loop -->
 <li><a href="{url}">{name}</a></li><!-- END category:loop --><!-- BEGIN entry -->
 <li><a href="{url}">{title}</a></li><!-- END entry -->
</ol>
<!-- END_MODULE Topicpath -->

スニペットを topicpath.html にコピペして <nav> を追加し、class を移植していきます。 完成形は以下のようになります。

Topicpathスニペット
<!-- BEGIN_MODULE Topicpath id="topicpath" -->
<nav class="topicpath">
<ol class="topicpath-list acms-container sp-container clearfix">
 <!-- BEGIN blog:loop -->
 <li class="topicpath-item"><a href="{url}" class="topicpath-link">{name}</a></li><!-- END blog:loop --><!-- BEGIN category:loop -->
 <li class="topicpath-item"><a href="{url}" class="topicpath-link">{name}</a></li><!-- END category:loop --><!-- BEGIN entry -->
 <li class="topicpath-item"><a href="{url}" class="topicpath-link">{title}</a></li><!-- END entry -->
</ol>
</nav>
<!-- END_MODULE Topicpath -->

Topicpathモジュールの条件設定

トピックパスモジュールでは、条件設定タブの引数についてカテゴリーとエントリーにチェックをつけるのを忘れないようにしてください。

また、モジュールID を設定すると階層の指定が可能になります。 例えば「お知らせ」カテゴリーの子カテゴリーに「テスト」というカテゴリーを作った時に「下階層のカテゴリーも含める」を選択するようにしてください。

階層設定では

  • 下階層を含めない
  • 下階層も含める
  • 下階層のみを対象とする

の3種類でデータの絞り込み範囲を設定ができます。

Topicpathモジュールの表示設定

表示設定タブでは、何も指定しないとトピックパスにブログ名が最初に表示されますので、HOME や TOP などの表記にしておきます。

トピックパスモジュールを利用すると、ブログ > 子ブログ > カテゴリー > 子カテゴリー > エントリー のように階層が自動的に作られ、リンクの設定もされます。

サイト内検索機能を実装する

各ページのサブカラムに用意されている検索フォームが機能するように実装していきます。

<div class="module-section">
  <section class="search">
    <div class="module-header clearfix">
      <h2 class="module-heading">検索</h2>
    </div>
    <form action="" method="post" name="searchForm" class="acms-form search-form" role="search">
      <div class="acms-form-action">
        <input type="search" id="searchForm" name="keyword" value="" size="15" class="search-form-input">
        <span class="acms-form-side-btn"><button type="submit" name="submit" class="acms-btn btn-search"><span class="acms-icon-search"></span><span class="acms-hide-visually">検索</span></button></span>
      </div>
    </form>
  </section>
</div>

この部分を少し書き換えます。

<div class="module-section">
  <section class="search">
    <div class="module-header clearfix">
      <h2 class="module-heading">検索</h2>
    </div>
    <form action="" method="post" name="searchForm" class="acms-form search-form" role="search">
      <div class="acms-form-action">
        <input type="search" id="searchForm" name="keyword" value="%{KEYWORD}" size="15" class="search-form-input">
        <input type="hidden" name="query" value="keyword">
        <span class="acms-form-side-btn"><button type="submit" name="ACMS_POST_2GET" class="acms-btn btn-search"><span class="acms-icon-search"></span><span class="acms-hide-visually">検索</span></button></span>
        <input type="hidden" name="tpl" value="/entry.html">
        <input type="hidden" name="bid" value="1">
      </div>
    </form>
  </section>
</div>

ポイントは以下の4点です。

  1. 既存のコードの input タグ内 value の空欄にvalue="%{KEYWORD}"を追加
  2. 既存のコードの button タグ内name="submit" をname="ACMS_POST_2GET"に書き換え
  3. input type="hidden" name="tpl" でPOST後のテンプレートファイルを指定
  4. type="hidden" name="bid" value="1" で検索範囲を指定(1:全部)

グローバル変数の %{KEYWORD} は、検索ワードを表示させる変数になります。

テンプレートのファイル名を変更し、テーマ設定ファイルを作る

静的なHTMLファイルだけで構成されていたウェブサイトが、a-blog cms を利用してブラウザからコンテンツの追加や更新が可能なサイトに生まれ変わりました。今回作ったテーマ sample をテーマ設定でテーマ名を選択するだけで動作するように設定ファイルを作ることと、ファイル名を標準的なものに変更します。

種類 旧ファイル名 新ファイル名
トップ index.html _top.html
一覧 list.html index.html
詳細 entry.html _entry.html

ファイル名の先頭にあるアンダーバーについて少し説明しておくと、アンダーバー付きのファイルはブラウザから見えなくなります。

http://localhost/http://localhost/top.html どちらでもページが出てしまわないように http://localhost/_top.html とすることで _top.html のリンク先は 404 not found になることが確認できます。

/themes/sample/template.yaml を最後に用意します。 上記のファイル名の変更で /themes/beginner/template.yaml からコピーしても同様ですが、以下をコピペしても大丈夫です。

tpl_top         : _top.html
tpl_index       : index.html
tpl_detail      : _entry.html
tpl_404         : 404.html
tpl_admin       : admin.html
tpl_entry_edit  : _entry.html
tpl_entry_add   : _entry.html
tpl_login       : login.html

最後に

今回は、いろいろなモジュールを中心に紹介しました。

  • OGPモジュール
  • インクルード処理
  • Navigationモジュール
  • Media_Bannerモジュール
  • Topicpathモジュール
  • サイト内検索機能
  • テーマファイルを作る

について紹介しました。

これで小規模なサイトのテーマ作成における大まかな一連の作業が終了しました。 どこにも PHP や JavaScript の実装はなく、 HTML と管理画面の設定で CMS 化の作業が完了します。

ぜひ、次はご自身で用意したオリジナルの静的HTMLファイルをベースとしたテーマ作成にチャレンジしてみてください。

続きで学べる「子ブログ編」を追加しました。これまでに作ったサイトを階層化された複数のブログを利用する構成に改良していくものになりますので、よろしければコチラもあせて学習ください。

https://zenn.dev/kazumich/articles/67c1a903d2b18b

Discussion