Posts on this page


January 27, 2016

Hugoが使える場合、使えない場合、使わなくて良い場合

Hugoはstaticなwebsite generatorです。ローカルマシン上に用意したファイルを、指定した規則に基づいてhtmlに変換して出力するソフトウエアです。サイト構築を行ってみて思う所を簡単にメモします。

更新頻度
リアルタイムで更新したい、日に何度も更新がある、アップロード頻度を上げることは好ましくない、という場合にはHugoは適切な手段とは言えないでしょう。コンテンツの一部にスクリプトを使って外部サービスからデータを呼び出すことで動的なページを作成することは可能ですが、それならばもともと動的なシステムを使えば良いように思われます。

サイトの規模
サイトの規模があまりに大きくなってくると、ローカルでのコンテンツのレンダリング時間が長くなり
ます。また差分の規模も大きくなればアップロードする時間が長くなるため、動的にコンテンツを生成するほうがストレスがないでしょう。

コンテンツの複雑さ
仮にコンテンツがブログのように時系列の1カテゴリのデータのみで構成されている場合は、既存のブログサービスに勝るものはないように思います。一方で、サイトの部分部分で異なった機能を持たせたい場合、例えば、サイトの一部はブログだが、他の部分は静的なページで、さらに他の部分にはメインのブログとは異なるが時系列の情報がある場合(例えば、テーマAのブログとテーマBの進捗報告が同じサイトに共存している場合)、既存のブログサービスやCMSで扱うのは困難になってきます。もちろん、WordpressやMoveble Typeではかなり柔軟にウェブページを作成できるのですが、作成者にしかわからないような絡み合った設定になってしまう点で課題が大きいように思います。それなら、希望の構造に合わせて柔軟にコーディングできるHugoのようなジェネレータに軍配が上がるでしょう(大規模なシステムなら、自前でphpを書いていけば良いのですが。)

セキュリティ
動的な製作環境の問題点の一つが、セキュリティアップデートと永久に付き合わないといけない点です。サーバー上にプログラムを配置する以上、常にセキュリティリスクにさらされているといえます。一方で、静的なサイトはサーバーそれ自体のセキュリティは依然として残るものの(例えば、ファイルそのものが書き換えられる)、プログラムに起因するリスクは根本的に取り除くことができ、管理の手間を大幅に減らすことができます。

SyntaxHighlighterを使ってHTMLを表示するためのエスケープ処理

inputエリアに変換したいhtmlコードを入力し、テキストエリアからフォーカスが外れると(tabキーを押すと)、outputエリアに変換されたテキストが表示されます。
input:
ourpur:

January 26, 2016

Hugoでトップページに更新情報を表示する

ウェブページのトップに、更新履歴の最初の10件を表示したい、今月のお知らせを表示したいといった場合で、過去の更新履歴や過去の月のお知らせは別ページに表示したいという場合にもHugoは便利な機能を持っています。
ここでは、更新情報のうち、最初の3件をトップページに表示することを考えます。
まず、更新情報は以下のように個別の.mdファイルとしてコンテンツを作成することにしましょう。
+++
date = "2016-01-01"
+++

あけましておめでとうございます!
+++
date = "2016-01-02"
+++

もうお正月も二日目。
+++
date = "2016-01-07"
+++

七草粥で健康に。
...
+++
date = "2016-03-05"
+++

そんなこんなで3月になりました。

次に作成したコンテンツの一覧ページを作成しましょう。更新情報を保存したwhats-newフォルダに対応させてレイアウトを作成します。
<html>
<body>
<p>更新情報の一覧:</p>
{{ range .Data.Pages }}
  <p>{{ .Date.Format "02 Jan 2006"}}</p>
  <p>{{ .Content}}</p>
{{ end }}
</body>
</html>

hugoを実行してレンダリングすると以下のようなページが作成されます。
<html>
<body>
<p>更新情報の一覧:</p>
<p>01 Jan 2016</p>
<p>あけましておめでとうございます!</p>
<p>02 Jan 2016</p>
<p>もうお正月も二日目。</p>
<p>07 Jan 2016</p>
<p>七草粥で健康に。</p>

...
<p>05 Mar 2016</p>
<p>そんなこんなで3月になりました。</p>
</body>
</html>

このリストの一部だけをトップページに表示するため、以下のようにindex.htmlのレイアウトを作成します。(トップページのみコンテンツ(.mdファイル)は存在せずレイアウトのみであることに注意してください。)
記事のデータを.Data.Pagesで参照し、Sectionが"whats-new"であるもののみを抽出、そのうち、最初の3件についてrangeで繰り返し処理して出力します。
<html>
<body>
<h1>トップページ</h1>
<p>更新情報(最新3件):</p>
{{ range first 3 (where .Data.Pages "Section" "whats-new" }}
  <p>{{ .Date.Format "02 Jan 2006"}}</p>
  <p>{{ .Content}}</p>
{{ end }}
<a href="whats-new/">...more</a>
</body>
</html>
レンダリングされたトップページは以下のようになり、更新情報の最初の3件が出力されました。なお、ここで最初の、としていますが、記事の順番は記事に指定されたdate、weight、ファイル名などによって決まりますので、希望する順番になるように適切にこれらを設定してください(通常はdateを設定しておけば、新しいものから順に並ぶ)。
<html>
<body>
<h1>トップページ</h1>
<p>更新情報(最新3件):</p>
<p>01 Jan 2016</p>
<p>あけましておめでとうございます!</p>
<p>02 Jan 2016</p>
<p>もうお正月も二日目。</p>
<p>07 Jan 2016</p>
<p>七草粥で健康に。</p>
<a href="whats-new/">...more</a>
</body>
</html>

HugoでCSVからデータを読み込んでテーブルを作成するには

Notice: Hugoを使用していて思ったのですが、CSVをドキュメント内に埋め込むという目的では以下の方法よりも、shortcodeを用いる方がより優れた方法かもしれません。

Hugoには外部データを読み込んでページを作成する方法が主に4つあります。
  1. config.tomlで定義したサイト変数(.Site.Params.variablename)を使う
  2. frontmatterで定義したページ変数(.Params.variablename)を使う
  3. データフォルダを使う(\data以下に保存して、.Site.Data.variablenameで参照)
  4. 外部データファイルをgetJSON, getCSVで読み込む

今回は4つ目にあたる外部データファイルの読み込みとその応用についてメモします。 また、ファイル形式としてはCSV形式を対象に説明していきます。

まず、読み込む対象となるCSV形式のデータを用意しましょう。エクセルやテキストエディタなど適当なソフトで作成してください。その際、文字コードはUTF-8を指定するようにしてください。間違ってShift-JIS等で保存すると文字化けの原因となります。保存先は、hugoから参照できるならばどこでも良いのですが、今回はローカルに保存することにします。
product, price, quantity
X001, 2, 30
X203, 3, 10
(staticフォルダ内に分かりやすくするため、csvフォルダを作成し、その中にdata.csvを保存する例)
次に、csvを出力する先のページコンテンツを作成します。
+++
type = "csv-table"
datafilename = "\static\csv\data.csv"
+++
この文章のあとにcsvから生成されたテーブルが表示されます。 そして、コンテンツ内でtypeで指定したレイアウトを作成します。
datafilenameのように.Paramsではすべて小文字の変数名しか使えない点に注意しましょう。getCSVは変数を二つ取る関数で、デリミタと読み込むファイル名を指定します。細かな話ですが、デリミタは1文字のみ指定が可能なのでミスタイプで余計なスペースが入らないように注意してください。getCSVで読み込んだデータを行数$iと$i行目のデータ$rに展開し、rangeで繰り返し各行について処理していきます。各行の内容は$rは配列なので、さらにrangeを使って各要素(テーブルのセル)ごとに処理を繰り返すことでテーブルを出力できます。なお、現在処理中の行数$iを使ってifで条件判断することで、行数に応じて処理を変えることができ、ここでは、1行目はthタグをそれ以降はtdタグを出力させました。


{{.Content}}


{{ range $i, $r := getCSV "," .Params.datafilename}}

{{ if eq $i 0}}
 {{range $r}}
  
 {{ end }}
{{ else }}
 {{range $r}}
  
 {{ end }}
 {{ end }}

{{ end }}
{{ . }} {{ . }}
これで、hugoを実行すれば、data.csvの内容が\public\dynamic-document\index.htmlにレンダリングされます。


この文章のあとにcsvから生成されたテーブルが表示されます。
productpricequantity
X001230
X203310
この手法の便利な点は既存のCSVデータを手軽にhtmlに変換できる、ということだけではなく、一度ウェブサイトを構築した後であってもdata.csvを更新し再度レンダリングすれば自由にテーブルの中身を変化させられるところにあります。
さらに、テンプレートをtypeとして定義したので、別のCSVファイルを別のコンテンツに出力することもできます。例えば、data2.csvとcsv-table-content.mdを作成しとします。
Hello, World
2, 1
+++
type = "csv-table"
datafilename = "\static\csv\data2.csv"
+++

今度は別のデータを別のファイルからレンダリングした結果が以下に現れます。
上記の2ファイルを作成し、hugoを実行すると、新たにcsv-table-contentが先ほどと同じcsv-tableレイアウトを使ってレンダリングされます。


今度は別のデータを別のファイルからレンダリングした結果が以下に現れます。
HelloWorld
21
なかなか便利な仕組みですよね!

January 15, 2016

Excelで文字色やセル色を切り替える/toggleする

Excelをテンポよく使うときにはマウスだけでなくショートカットキーを使えるようになると、とても便利なのですが、そうは言ってもすべてのショートカットキーを覚えるのは大変ですし、セルや文字の色を変更するショートカットは打鍵数が多いため必ずしも便利とは言えません。それほど頻繁に使わない機能であれば、ALTキーから初めて一連のリボンのメニューをたどっていくようにキーを使えば良いですが、文字色を変えるためにいちいちキーを連打するのも煩わしい、ということで、ショートカットキーとマウスによるリボンの操作の間に位置するのがクイックアクセスツールバーかと思います。

クイックアクセスツールバーから任意のマクロを実行できるので、よく使う、比較的複雑な操作をマクロにまとめておき、それをクイックアクセスツールバーに登録すると、マウスでワンクリック、キーボードからはALT→数字で実行できるので便利です。また、マクロをクイックアクセスツールバーに登録する際には表示するアイコンを選ぶことができるので、何の機能なのかを、アイコンを目安に思い出すことができるので便利です。

前置きが長くなってしまいましたが、文字の色を切り替えるマクロを以下に残します。色の順序は設定部分のみ書き換えることで自由に変更できます。カラーインデックスは代表的なものはコメントに残しましたがgoogle等で検索すると色々あることが分かります。
Sub ToggleCellFontColor()
    Dim Default_Color As Integer, ColorSetting() As Variant
    Dim Colors As Collection
    
    ' Color settings
    ' Refer color by ColorIndex
    '1:Black, 2:White
    '3:Red, 4:Green, 5: Blue
    '6:Yellow, 7:Magenta, 8:Cyan
    Default_Color = 1       'black
    ColorSetting = Array(3, 4, 5, 6, 7, 8, 2, 1)
    
    'Configuration for color array
    Set Colors = New Collection
    For i = LBound(ColorSetting) To UBound(ColorSetting)
        Colors.Add CStr(ColorSetting((i + 1) Mod (UBound(ColorSetting) + 1))), CStr(ColorSetting(i))
    Next
    
    'Setting ColorIndex of Font object
    On Error Resume Next
        Selection.Font.ColorIndex = Colors.Item(CStr(Selection.Font.ColorIndex))
    If Err.Number <> 0 Then Selection.Font.ColorIndex = Default_Color
    
End Sub
なお、セルの色を切り替えたい場合は、上記コードのSelection.Font.ColorIndexをSelection.Interior.ColorIndexに修正します。

ColorIndexの一覧:
http://dmcritchie.mvps.org/excel/colors.htm