markdownのテーブルでセル結合を行う
標準のmarkdownではテーブルのセル結合が実施できませんが、時折セル結合が欲しくなるので対応しておきました。

やりたいこと

本サイトは世界最速(The world’s fastest framework for building websites)という謳い文句で知られる、 Hugo によって構築されています。

Hugoでは記事はmarkdownで記述するわけですが、たまにmarkdownゆえに表現力が少し乏しいと感じることもあります。 (それが好都合だとも思っていますが)

例えば以下のような乳幼児の体重・身長の表1 があった場合

生後体重(男)体重(女)身長(男)身長(女)
0月3.002.9449.048.5
1月4.794.4755.654.6
2月5.845.4259.157.9
3月6.636.1562.060.7
4月7.226.7164.363.0
5月7.667.1466.264.9

ではなく

生後体重身長
0月3.002.9449.048.5
1月4.794.4755.654.6
2月5.845.4259.157.9
3月6.636.1562.060.7
4月7.226.7164.363.0
5月7.667.1466.264.9

とした方が分かりやすくないですか?

とにかくはじめます🍛

markdown-it

上記のような表は markdown-it と呼ばれるモジュールおよびそのプラグインを使用すると実現できます。

そしてHugoのショートコードを利用して、特定のmarkdownだけmarkdown-itを使って変換をさせます。

つまりこんな感じ

{{<markdown>}}
ここは`markdown-it`で処理させる
{{</markdown>}}

Hugoのmarkdownエンジンを変更するのではなく、特定のmarkdownだけを変換対象とする考え方です。 これによりできるだけ世界最速の邪魔をしないようにします。

ショートコードの作成

markdown文字列は netlifyの Functions を通じてmakdown-itにより変換するだけです。

markdown.html
{{ $query := .Inner | base64Encode | querify "s" | printf "%s" }}

{{ $endpoint := printf "%s/markdown?" $.Page.Site.Params.api_endpoint}}
{{ $jsonData := getJSON $endpoint $query }}
{{ $html := $jsonData.m }}

{{ safeHTML $html }}

ちなみにquerifyを使ってエンコードしないと、 Base64でエンコードされた+記号がURLではスペースに変換されてひどいことになります。

Functionsの作成

Functionsについては以前の記事も参考にしてください。

何もわからないこの世の中をなんとか生きていくためにデータ解析を始めたカレーのブログ

まず必要なモジュールをインストールします。 テーブルの変換には markdown-it-multimd-table というプラグインを使います。

$ npm install makdown-it markdown-it-multimd-table

あとはこれで変換する処理を行う関数を書きます。

assets/markdown.js
const md = require('markdown-it')()
  .use(require('markdown-it-multimd-table'),
       {enableRowspan: true})
exports.handler = (event, context, callback) => {
  const s = event.queryStringParameters.s
  const t = Buffer.from(s, 'base64').toString()

  callback(null, {
    statusCode: 200,
    "headers": {
      "Content-Type": "application/json; charset=utf-8",
    },
    body: JSON.stringify({
      html: md.render(t)
    })
  })
}

行結合もサポートするため{enableRowspan: true}を付けています。

結果

冒頭のテーブルはmarkdownショートコードを利用して、以下のように記述すれば生成されるようになりました。

|生後    | 体重             || 身長             ||
|^^      | 男      | 女      | 男      | 女      |
|------- | ------- | ------- | ------- | ------- |
|0月     | 3.00    | 2.94    | 49.0    | 48.5    |
|1月     | 4.79    | 4.47    | 55.6    | 54.6    |
|2月     | 5.84    | 5.42    | 59.1    | 57.9    |
|3月     | 6.63    | 6.15    | 62.0    | 60.7    |
|4月     | 7.22    | 6.71    | 64.3    | 63.0    |
|5月     | 7.66    | 7.14    | 66.2    | 64.9    |

おまけ

ちなみにオプションやプラグインを設定すれば、テーブル以外も表現の幅は広がります。

例えばhtmllinkifyオプションを有効にすると

Option   | サンプル
-------  | ------
html     | <div style="transform:rotate(-30deg);">回転</div>
linkify  | gohugo.io

は以下のように表示されます。

  • htmlはhtmlタグを直接記入可能
  • linkifyはリンクを自動で判別
Optionサンプル
html
回転
linkifygohugo.io

htmlを直書きする機会は少ないですが、likifyはリンク集などを作る際には便利かもしれません。

追記(2019/12/15)

Hugoの0.60.0よりマークダウンのエンジンが goldmark になったようです。2

これによりlinkifyなど CommonMark に準拠した機能であれば標準でも利用可能になりました。

ただ本記事でやりたかったセル結合などはできないので、やはりmarkdown-itはまだ必要になりそうです。


  1. 平成22年度:乳幼児身体発育調査 ↩︎

  2. Now CommonMark Compliant! | Hugo ↩︎

最終更新:2021/08/31 22:54 (Tue)