概要
Markdown と Pandoc を使用して、HTMLとCSSのみで構成されたお手軽運用ホームページを作成します。
CGIやCMSを使用しないので、格安のレンタルサーバーでも運用が可能と考えられます。
問い合わせとかについては他サービスを利用します。
それによって、全体の運用コストを削減します。
最後に使用したテンプレートを記載しておりますので、サイト作成の参考にして頂ければと思います。
検証環境
- OS: Ubuntu 22.04 LTS AMD64
- LXDコンテナを作成してその中で構築
- Pandoc: 3.1.12.1
インストール
最新のバージョンを使用するため、あらかじめ公式サイトからdebファイルをダウンロードしてインストールします。
debを直接入れるため、LXDコンテナを作ってその中で構築するのがオススメです。
$ apt install pandoc-3.1.12.1-1-amd64.deb
テンプレートの作成
表示を柔軟に変更するために、テンプレートファイルをエクスポートして改良します。
主に必要のない部分を削除したり、レイアウトを自分好みに変更します。
$ pandoc -D html5 > template.html
Markdownファイルを作る
コンテンツの情報をこちらに入れます。
変数の設定
まず、タイトル等の設定を入れます。
また、SNSアカウント等もこちらに入れて表示に使用します。
---
css:
- ./css/exclusive.css
- ./css/common.css
title: やわ音原ミキサー
subtitle: あなたの動画にソフトウェアトークを入れて、より魅力的に!
description-meta: やわ音原ミキサーの公式サイトです
author:
- 兎のあす
keywords:
- やわ音原ミキサー
- ニコニコ動画
sns:
- link: https://github.com/Usagno8su/YawaOngenMixer
title: CUI版
github: true
icon: ./pic/github-mark-white.svg
- link: https://github.com/Usagno8su/YawaOngenMixer_doc
title: CUI版ドキュメント
github: true
icon: ./pic/github-mark-white.svg
- link: https://www.nicovideo.jp/user/4448412
title: ニコニコ動画
niconico: true
icon: ./pic//niconico-siro.png
- link: https://twitter.com/YawaOngenMixer
title: 公式X(旧Twitter)
twitter: true
icon: ./pic/x-logo.svg
...
行った工夫としては、CSSを外部ファイルにしている点です。
CSSはHTMLファイル内に記載して一つのファイルにすることができるのですが、CSSに変更があった場合に毎回ビルドを行う必要があります。
その手間を削減するために、外部ファイルに記載してそのパスを記載しています。(画像ファイルについても同様)
また、SNSアカウントについてもこちらに記載し、後ほどそれぞれのアイコンをリンクにします。
テンプレートの仕様について
冒頭で出力したPandocのテンプレートファイルの仕様について説明します。
変数
$
マークで囲われた文字を変数と認識します。
$title$
if文
if文により変数に値が入っている時のみ表示するような動作が可能です。
$if(title)$
<h1 class="title text-center title-color title-size">$title$</h1>
$endif$
<h1 class="title text-center title-color title-size">やわ音原ミキサー</h1>
for文
for文により複数の値を入力できます。
冒頭の変数一覧について、CSSは複数ありますが、これは配列となっており、複数の値を指定できます。
それを一つずつ出力できます。
$for(css)$
<link rel="stylesheet" href="$css$" />
$endfor$
<link rel="stylesheet" href="./css/exclusive.css">
<link rel="stylesheet" href="./css/common.css">
特殊な変数について
いくつかの変数については、ビルド時にコマンドでないようを指定できます。
- header-includes
-
-H
オプションで指定されたHTMLファイル
-
- include-before
-
-B
オプションで指定されたHTMLファイル
-
- include-after
-
-A
オプションで指定されたHTMLファイル
-
- body
- Markdownファイルの本文
本文へのCSS適用
本文内にCSSを適用させるには、以下のように適用させたい文章を囲みます。
::::{.item-justify-center}
この部分に適用させます。
::::
これで、::::
の範囲を<div>
タグで囲んでitem-justify-center
というCSSを適応することができます。
<div class="item-justify-center">
<p>この部分に適用させます。</p>
</div>
また、出力されるタグに直接CSSを適用することも出来ます。
## この部分に適用させます。1 {.item-justify-center}
`この部分に適用させます。2`{.item-justify-center}
出力結果は下記のようになります。
<h2 class="item-justify-center">
この部分に適用させます。1
</h2>
<code class="item-justify-center">
この部分に適用させます。2
</code>
テンプレートの分割
テンプレートを分割し、ヘッダーとフッターを別々に分けます。
これは、将来的に複数ページのサイトにする場合、それぞれを使い回せるようにするためです。
テンプレートにbody
の変数を入れなければ本文は出力されないので、元になるMarkdownファイルはメインのものと同じものを使用できます。
分割したファイルは最後にメインページを作成する際に結合します。
SNSアカウント
SNSアカウントについては増えたり変わったりする場合もあるため、それに柔軟に対応できるようにします。
まず、各SNSアカウントの公式アイコンを予め取得しておきます。
そして冒頭のsns
変数にそれぞれ設定します。
連想配列を配列化しており、各項目の設定は以下となっています。
- link: SNSアカウントのリンク
- title: アカウントの説明
- icon: アイコンファイルのURL
- github: アカウントのタイプとなります
最後のアカウントのタイプについてですが、
本当はtype: github
といった形にしたかったのですが、Pandocのif文を$if(sns.type==='github')$
という形にできなかったため、このような形にしています。
これにより、githubアカウントのみ表示したい場合は$if(sns.github)$
で判別できます。
すべてのアカウントを表示したい場合は下記のようにすればできます。
$if(sns)$
$for(sns)$
<a href="$sns.link$" target="_blank" rel="noopener noreferrer">
<img src="$sns.icon$" alt="$sns.title$" title="$sns.title$" width="30" height="30" class="margin-icon-r" />
</a>
$endfor$
$endif$
デザインについて
これについては用途によって色々と差異があるかと思います。
私は簡単なシングルページのサイトにするため、内容をまとめたポスターを作るようなイメージで作成しました。
デイレクトリ構成
使いやすや等も考えて、以下のようにしてみました。
- bin: ビルド用のスクリプト等
- component: ヘッダーやフッターのHTMLファイル
- outHTML: レンタル鯖へアップするファイル(HTMLファイルの出力先)
- css: cssファイル
- pic: 画像素材とか
- src: 元となるMarkdownファイル
- template: Pandocのテンプレートファイル
ビルドの実行
まずヘッダーとフッターをビルドします。
# ヘッダーを作成
$ pandoc src/top.md -s -o component/header.html --template=template/header-template.html
# フッターを作成
$ pandoc src/top.md -s -o component/footer.html --template=template/footer-template.html
その後それらをあわせてビルドしてファイルを完成させます。
$ pandoc src/top.md -s -o outHTML/top.html -B component/header.html -A component/footer.html --template=template/top-template.html
これらをシェルスクリプトとして作成して、コマンド1回ですべてをビルドできるようにしています。
-B
で指定したファイルはの下記の所に入ります。(複数指定可能)
$for(include-before)$
$include-before$
$endfor$
-A
で指定したファイルはの下記の所に入ります。(こちらも複数指定可能)
$for(include-after)$
$include-after$
$endfor$
参考URL
- Pandoc公式マニュアル
- Pandoc User’s Guide 日本語版
- footerを最下部に固定する:CSSのプロパティ4行でOK
- 【HTML】基本のリンク&別タブでリンクを開くコードと注意点
- PandocのHTML出力でGFMとカスタムテンプレートを使う
- Pandoc Markdownで任意の要素にクラス/IDを指定する
- markdownでHTMLのidやクラスなどの属性を指定 - 愚鈍人
テンプレート一覧
$-- ヘッダー
<header id="main-header" class="header-sta position-fixed item-justify-between bg-transparent">
<div class="item-width-25pt"></div>
<div class="item-width-50pt item-justify-center">
</div>
<div class="item-width-25pt item-justify-end">
$if(sns)$
$for(sns)$
$if(sns.github)$
<a href="$sns.link$" target="_blank" rel="noopener noreferrer">
<img src="$sns.icon$" alt="$sns.title$" title="$sns.title$" width="30" height="30" class="margin-icon-r main-coloer round-9999 padding-1px" />
</a>
$endif$
$endfor$
$endif$
</div>
</header>
$-- 下のリンク一覧等
<footer class="linkkist-position bar-color">
<div class="item-justify-between">
<div>
</div>
<div class="item-width-50pt item-justify-center">
</div>
<div class="margin-icon-r item-width-25pt item-justify-end">
$if(sns)$
$for(sns)$
<a href="$sns.link$" target="_blank" rel="noopener noreferrer">
<img src="$sns.icon$" alt="$sns.title$" title="$sns.title$" width="30" height="30" class="margin-icon-r" />
</a>
$endfor$
$endif$
</div>
</div>
<div class="item-justify-center">
<div class="copy-light">
copyright © $for(author-meta)$ $author-meta$. $endfor$ All Rights Reserved.
</div>
</div>
</footer>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
$for(author-meta)$
<meta name="author" content="$author-meta$" />
$endfor$
$if(date-meta)$
<meta name="dcterms.date" content="$date-meta$" />
$endif$
$if(keywords)$
<meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" />
$endif$
$if(description-meta)$
<meta name="description" content="$description-meta$" />
$endif$
<title>$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$</title>
$for(css)$
<link rel="stylesheet" href="$css$" />
$endfor$
$for(header-includes)$
$header-includes$
$endfor$
</head>
<body class="body-st">
$for(include-before)$
$include-before$
$endfor$
$-- タイトル
$if(title)$
<div id="title-block-header" class="main-coloer main-title-position">
<h1 class="title text-center title-color title-size">$title$</h1>
$if(subtitle)$
<p class="subtitle text-center title-color">$subtitle$</p>
$endif$
</div>
$endif$
$-- メインコンテンツ
<div class="main-con">
$body$
</div>
$for(include-after)$
$include-after$
$endfor$
</body>
</html>
/* 汎用的に使用するCSS */
.text-center{
text-align: center;
}
.title-size{
font-size: 64px;
}
.title-color{
color: #e8ecef;
}
.bar-color {
background-color: #185790;
}
.bg-transparent{
background-color: transparent;
}
.round-9999{
border-radius: 9999px;
}
.position-fixed{
position: fixed;
}
.item-justify-between{
display: flex;
justify-content: space-between;
}
.item-justify-center{
display: flex;
justify-content: center;
}
.item-justify-end{
display: flex;
justify-content: end;
}
.item-width-25pt{
width: 25%;
}
.item-width-50pt{
width: 50%;
}
.margin-icon-r{
margin-right: 6px;
}
/* 各要所の専用CSSを入れる */
.body-st{
margin: 0;
display: flex;
flex-flow: column;
min-height: 100vh;
background-color: #e9e9e9;
color: #203354;
}
.main-title-position{
margin: 0 calc(50% - 50vw);
padding-top: 16px;
padding-bottom: 8px;
width: 100vw;
}
.main-coloer{
background-color:#185790;
}
.header-sta{
margin-top: 0px;
padding-top: 2px;
padding-bottom: 3px;
width: 100vw;
border-color: black;
border:2px;
}
.linkkist-position{
margin-bottom: 0;
margin-right: 0;
margin-left: 0;
padding-top: 16px;
padding-bottom: 12px;
width: 100vw;
}
.main-con {
flex: 1;
margin-left: 10px;
margin-right: 10px;
}
.copy-light{
color: #e8ecef;
}