Redmine テーマ minimalflat2 v1.2.0 リリース
Redmine v3.3 が提供されたので、それに対応する minimalflat2 v1.2.0 をリリースした。
Redmine v3.3 標準テーマは v3.2 以前と互換がないため minimalflat2 v1.2.0 も Redmine v3.3 以降をサポート対象とする。旧バージョンを Releases に残しておくので古い Redmine 対応版が必要な場合はこちらを利用してもらう。v1.1.5 の Release Notes にも、これが Redmine v3.2 をサポートする最終版であることを記載しておいた。
以下は作業記録。
Redmine 3.2 と 3.3 の差分反映
minimalflat v1.0.0 では Redmine v3.1 の application.css
を Stylus 化して部位ごとにファイルを分割した。このテーマでは標準の application.css
を import せず、すべてのスタイルを独自定義している。そのため自身で管理しやすいように Stylus を構成。
しかし Redmine 本体側の変更を確認する際に application.css
の前後バージョン diff と Stylus を一致させるのが面倒になってきた。そこで今回から、Stylus ファイルの分割は最小にとどめ、元の 定義順をなるべく維持するようにした。ファイルこそ長大になったものの差分の確認と反映がおこないやすい。ちなみに diff は以下のようにチェックしている。
- Download - Redmine から差分を確認する前後バージョンを入手
- それぞれの
application.css
やresponsive.css
の diff を FileMerge でチェック
FileMerge というのは Xcode 付属の GUI つき diff ツールである。単体で起動するために
/Applications/Xcode.app/Contents/Applications/FileMerge.app
を Dock に登録している。Finder からアクセスする場合は Xcode.app のコンテキストメニューからパッケージの内容を表示を選択して Contents > Applications を開く。
余談だが Contents > Developer > Applications には iOS シミュレータもある。これを Dock に入れておくと便利だ。Web フロントエンド開発しているとき browser-sync とかでホストさせて iOS シミュレータ上の Safari から動作確認したりする。
.icon と .icon-only
Redmine v3.2 まではチケットのコメント編集アイコンなどは <img>
になっていた。v3.3 ではこれらの設計が改善されて <a>
の背景画像に変更されている。
minimalflat2 ではアイコンをフォントにしており、対象となる要素の before
擬似要素に定義している。しかし <img>
は置換要素だから擬似要素は利用不能。仕方ないので theme.js
によって特定の src
属性を持つ <img?
を検出したら <i>
へ置換するようにしていた。
この処理は無駄であるうえ <img>
に click
が指定されていたら継承が必要などの問題がある。v3.3 でようやくこの対策処理が不要になった。最新の theme.js
ではプロジェクト一覧画面のツリー開閉 UI だけ担当している。
アイコンに関連しては、もうひとつ重要な変更がある。
これまで minimalflat2 では .icon
を定義していなかった。これはアイコン関連をすべてフォントに置き換えるため、標準の background-image
と padding
系を組み合わせた指定が干渉するためである。
しかし今回から .icon-only
と共に標準のスタイル指定そのままに移植するようにした。どうやら一部の Redmine プラグインでは標準の .icon
に依存しているらしく、それらへ個別対応するのはキツイ。ならばこの定義を残して必要な部分だけ上書きするほうが設計的に好ましいと判断した。
上書きの工夫について。まずは普通に Stylus で
.icon {
background-position 0% 50%
background-repeat no-repeat
padding-left 20px
padding-top 2px
padding-bottom 3px
}
.icon-only {
background-position 0% 50%
background-repeat no-repeat
padding-left 16px
}
と定義。しかし HTML 上の .icon
や .icon-only
の指定は
<a title="Delete relation" class="icon-only icon-link-break">Delete relation</a>
のようになっている。そのまま .icon-XXXX:before
でアイコン フォントを指定すると .icon
や .icon-only
のレイアウトに影響されてしまう。これを上書きするため、
.icon {
&.icon-link-break,
&.icon-link-edit, ... {
padding 0
}
}
.icon-only {
&.icon-link-break,
&.icon-link-edit, ... {
width 1.3em
height 1.3em
padding 0
font-size 1em
color transparent !important
&:after {
content ""
}
}
}
とした。Stylus は &
で親階層を表す。そのためこれらは .icon.icon-link-break
という形式へコンパイルされる。つまり class として同時指定された時のみ定義を上書きして影響を相殺しているのだ。
- *2016/7/13 修正 v1.2.0 時点では height:auto にしていた。しかしこの指定だと透明にしたテキストが
width
に満たず折り返されたとき、その分の高さが計上されてレイアウトが崩れる。そのためheight
もwidth
と同じ固定値へ修正。またcolor
は issue の関連チケット表示で優先度の高いものがあると、それに対して色が指定されるためtransparent
だけだと詳細度の関係でテキストが可視化されてしまう。よって!important
により透明化を強制するようにした。
階層化されたプロジェクトのタイトル
従来、階層化されたプロジェクトのタイトルはこんな感じの HTML になっていた。
<h1>
<a class="root" href="/redmine/projects/root?jump=overview">Root</a> »
<a class="ancestor" href="/redmine/projects/parent?jump=overview">Parent</a> »
Current
</h1>
class
こそ設定されているが、テーマで明示的に指定しない限り文字サイズは <h1>
なので、長いタイトルが続くとレイアウトが崩れる問題があった。Redmine v3.3 ではこれが改善されて
<h1>
<span class="breadcrumbs">
<a class="root" href="/projects/root?jump=overview">Root</a>
<span class="separator"> » </span>
<a class="ancestor" href="/projects/parent?jump=overview">Parent</a>
<span class="separator"> » </span>
</span>
<span class="current-project">Current</span>
</h1>
となる。そして CSS では
#header h1 .breadcrumbs {
display: block;
font-size: .6em;
font-weight: normal;
}
のように文字サイズ調整されていた。つまり上層プロジェクトのタイトルは小さくなる。あわせて他方で text-overflow:ellipsis
と white-space:nowrap
が指定されているのでカレントを目立たせつつ長さを短縮、行が維持されてレイアウト崩れは回避された。
しかし minimalflat2 ではタイトルの <h1>
に対して before
擬似要素でアイコン表示している。そのため .breadcrumbs
の display:block
が影響して改行されてしまう。よって display:inline-block
へ修正する必要があった。
これは minimalflat2 独自の事情だが、それを抜きにしてもインライン要素についてレイアウト互換を維持しながらブロック要素にするならば、display
は inline-block
にしておくのが無難である。
リリース用 ZIP ファイル名処理の改善
これは前バージョンで対応した内容だが、記録していなかったので改めて。
minimalflat2 は GitHub プロジェクトの Releases に ZIP ファイルとしてリリースしている。このファイル、名前にバージョン番号を付与しているのだが、これまでは npm-scripts で変数を参照できなかったため以下のようにハードコードしていた。
{
"scripts": {
"release:archive": "bestzip minimalflat2-v1.1.5.zip ./minimalflat2"
}
}
バージョン番号の設定はプロジェクトにひとつであるべきだ。minimalflat2 はプロジェクト情報を package.json
で管理しているから、その version
を一意として参照するのが好ましい。というわけで cross-conf-env を利用して以下のように修正。
{
"version": "1.2.0",
"scripts": {
"release:archive": "cross-conf-env bestzip minimalflat2-vnpm_package_version.zip ./minimalflat2"
}
}
ハードコードしていた部分が npm_package_version
になっている。これは process.env.npm_package_version
に相当し、cross-conf-env が解析して当該変数の値に置換してから bestzip に処理を受け渡す。
この対応により今後は version
を修正するだけで ZIP ファイル名へ反映されるようになった。