Hugoテーマをアップデートした

まえに数式を導入した。使っていたら // による改行が反映されないことに気が付いた。 実験したところ使っているテーマ(minimo)のcssと干渉していそうだと推察された。

調べたところminimoの最新にはKaTeXのショートコードが追加されていた。 そのためアップデートして、それを利用することに決めた。

しかしテーマに改変を加えていたため簡単にアップデートできなかった。 そこで改変部分を切り離すことにした。せっかくCSSをさわるので機能改善も行うことにした。 ついででやった機能改善は youtubeショートコードのレスポンシブ対応。

観点 なかみ
やったこと Hugoのテーマ(minimo)を最新にした
目的 KaTeXと既存テーマのスタイル定義の衝突を回避する
起きた問題 既存テーマへのパッチの内容を移植する必要が出てきた
対応 ショートコードをテーマから本体へ移動, cssのビルド, 既存マークダウンの変換
使った道具 webpack,npm,hugo,vim

では振り返る。 アップデートに向けてやった流れを下に書く。

  1. ./theme/minimo/layouts/shortcodes/ 配下の独自ショートコードをプロジェクトルート配下の ./layouts/shortcodes/ へ動かす
  2. ./webpack.config.js でSCSSのビルドを定義
  3. 改変テーマのSCSSから欲しい部分をコピペ
  4. 既存マークダウンの変更

そして、その後 youtubeショートコードをレスポンシブにするSCSSを追加した。

1.,3.,4.については特に書くことはない。2.そしてついでのyoutubeのSCSSについてメモする。

SCSSビルドの準備

ディレクトリ構成はこんな感じ。Node.js久しぶりだ。 package.json,webpack.config.js はminimoからコピペで取ってきて不要なパッケージや処理をしない様に削って作った。

ディレクトリ構成は下になった。

./package-lock.json
./package.json
./webpack.config.js
./static/css/customize.css
./src/stylesheets/customize.scss
                 /layouts/_layouts.scss
                 /shortcodes/_shortcodes.scss
                            /_alert.scss
                            /_figure.scss
                            /_shortcodes.scss
                            /_youtube.scss
./dist/

package.json はこちら。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
  "name": "blog-dirtycache",
  "description": "private blog of @masu_mi",
  "version": "0.0.1",
  "author": {
    "name": "Masumi Kanai",
    "url": "https://blog.masu-mi.me"
  },
  "repository": "https://bitbucket.org/masu-mi/blog-dirtycache/src/master/",
  "license": "MIT",
  "scripts": {
    "build": "NODE_ENV=production webpack",
    "start": "hugo server --disableFastRender",
    "watch": "webpack --watch --progress --colors"
  },
  "devDependencies": {
    "autoprefixer": "^9.6.0",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^2.1.1",
    "cssnano": "^4.1.10",
    "mini-css-extract-plugin": "^0.7.0",
    "node-sass": "^4.12.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "webpack": "^4.32.2",
    "webpack-cli": "^3.3.2"
  },
  "dependencies": {
    "normalize.css": "^8.0.0"
  }
}

下みたいに開発環境を準備した。

1
2
nodebrew install v12.7.0
npm install

そしてwebpack.config.jsは下の通り。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
const path = require('path')
const cssnano = require('cssnano')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCSSExtractPlugin = require('mini-css-extract-plugin')

const extractCSS = new MiniCSSExtractPlugin({
  filename: '../static/css/[name].css'
})

const cleanBuild = new CleanWebpackPlugin({
  cleanOnceBeforeBuildPatterns: [
    path.resolve('static/css/*'),
  ]
})

const node_env = process.env.NODE_ENV
const config = {
  mode: node_env === 'production' ? 'production' : 'development',
  entry: {
    customize: path.join(__dirname, 'src/stylesheets', 'customize.scss')
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        include: [path.resolve(__dirname, 'src/stylesheets')],
        use: [
          MiniCSSExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1
            }
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                autoprefixer(),
                'production' === node_env
                  ? cssnano({
                      preset: [
                        'default',
                        { discardComments: { removeAllButFirst: true } }
                      ]
                    })
                  : null
              ].filter(Boolean)
            }
          },
          'sass-loader'
        ]
      }
    ]
  },
  resolve: {
    extensions: ['*', '.scss']
  },
  plugins: [extractCSS]
}

if (node_env === 'production') config.plugins.push(cleanBuild)

module.exports = config

このビルドの設定を元にビルドした。

1
webpack build

webpack.config.jsの補足

設定について少し補足する。

entry フィールドはエントリポイントでビルドのスタート地点になるファイルを指定している(複数可能)。

module がそのエントリポイントのファイル達に対して適用するモジュールが記述される。 modle.test, module.include などのフィールドがファイル名に対するパターンマッチになっている。

今回の場合は*$(pwd)/src/stylesheets* 配下の .scss ってサフィックスを持つファイルを対象に適用される。 他にも exclude ってフィールドで除外も定義できる。 include と衝突した場合の解決順序は知らない。

use に適用したいプラグインをリストにして渡す。なんと 後ろから 適用される。 なので、この場合まず sass-loader が呼ばれ postcss-loader に渡り css-loader を経て最後に MiniCSSExtractPlugin.loader に渡る。

sass-loadersass を読み込み処理するのに必要なプラグインで node-sass に依存している。 sass から css に変換する。

postcss-loader は完成した css を再度パースしてASTを作って各種プラグインに渡すことで出力を最適化するフレームワークとして振る舞うプラグインらしい。そして cssnano は時代遅れのベンダープレフィックス除去や圧縮してくれる。 css-loaderwebpackcss を扱うためのものらしいからきっと内部的に JavaScript のオブジェクトにする機能があるのでしょう。 最後にmini-css-extract-plugincss ファイルとして外部に書き出す。 mini は軽量なって意味らしい。

SCSSの簡易の説明

よくわかってないけどCSSを基本に調べれば、だいたいなんとかなる。ただしインポートの仕組みは大事。 インポートは下みたいに定義する。

1
@import 'variables/variables';

そうすると記載しているファイルのあるディレクトリから相対的に解決される。 ただし / 区切りの最後の名前に対してアンダーバー(_)をプレフィックスに .scss をサフィックスに持つファイルが解決される。 なのでこの場合は ./variables/_variables.scss ファイルが読み込まれる。

ついでのCSSでアスペクト比を固定する。

SCSSは下の様に定義した。参考にしたというかコピーさせてもらったのは"How do I make a full-width `iframe` with fixed aspect ratio?“です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
.ext-block {
  position: relative;
  width:     90%;
  &:before {
    content:"";
    display: block;
    padding-top: 63%;
  }
  &-frame {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    width: 100%;
    height: 100%;
  }
}

利用するショートコードは下みたいに書き換える。 (以前は固定値をデフォルトにして埋め込み時に明示的に指定できる様にしていた)

1
2
3
4
5
6
<div class="ext-block">
  <iframe class="ext-block-frame"
  {{ if $.Get "title" }} title="{{ $.Get "title" }}" {{ end }}
  src="https://www.youtube.com/embed/{{ $.Get "id" }}" frameborder="0"
  allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>

開発時には npm run watch していた。 package.json で定義されている通り webpack –watch –progress –colors が実行される。 scss を書き換えると勝手にビルドしてくれる。 プロジェクトに必要な操作は面倒でも全て俺が明示的に保持するって感じの圧力を感じた。 Makefile よりも手続き的というか開発フローに積極的に介入してくる感じ。

comments powered by Disqus