Redmine theme minimalflat2 v1.2.2 release

2016年10月24日 0 開発 , ,

長らく放置していた minimalflat2 を v1.2.2 としてリリースした。

今回の変更点は以下。

大きな変更、というか方針転換として Redmine プラグイン対応がある。

テーマ側で特定のプラグインに対応すると、それらの更新に影響を受けるため避けてきた。しかし何件か PR で対応されたことから考えを改めた。

現在の方針としては

  • 最新の Redmine に対応していること
  • Vagrant の最新 Redmine box で動作確認できること
  • テーマとして対応が容易であること
  • GitHub issues にて要望されること

を満たしたものについては対応することにした。なお、この条件は意外に厳しい。

かの有名な Redmine CMS の対応を要望されたのだが、依存 gem の関係か bundle に失敗、そのまま Redmine を再起動したら 500 error になってしまった。ログを見るに Active Record の参照問題っぽいが、それはテーマ側で修正するものではなく、どうにもならない。

前に Redmine 運用の記事でも書いたが、Redmine プラグインは gem 依存が自身で完結しておらず、うまく解決されないと Redmine 本体がクラッシュする。

要望があっても私の環境で動作確認しないことには対応できないわけで、今のところ gem 未使用なプラグインとか Redmine 最新版に追従できてるものだけサポートという状態である。

放置していたものをリリースすることになったのはこの issueで修正したはずの問題が再報告されたため。

開発者としては commit/push 時点で終わったつもりになっていたけど、それを反映したものをリリースしなければ意味がない。半端に修正したまま放置というのはいかにも無責任である。

ということに気づいたのでリリースとあいなった。

あと、対応するバージョンを決めかねる issue は v.NEXT という Milestone を設定することにした。Redmine でも同じような運用をしているのだが、将来に見送るものはそうであることを明示しておくと issue の状態がわかりやすくなる。

Redmine テーマ minimalflat2 v1.2.0 リリース

2016年7月5日 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 は以下のようにチェックしている。

  1. Download – Redmine から差分を確認する前後バージョンを入手
  2. それぞれの application.cssresponsive.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-imagepadding 系を組み合わせた指定が干渉するためである。

しかし今回から .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:ellipsiswhite-space:nowrap が指定されているため、カレントを目立たせつつ長さを短縮し、行が維持されてレイアウト崩れは回避された。

しかし minimalflat2 ではタイトルの h1 に対して before 擬似要素でアイコン表示しているため、そのままだと .breadcrumbsdisplay:block が影響して改行されてしまう。よって display:inline-block へ修正する必要があった。

これは minimalflat2 独自の事情であるが、それを抜きにしても、あるインライン要素についてレイアウト互換を維持しながらブロック要素にするならば、displayinline-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 を修正するだけでファイル名へ反映されるようになった。

WordPress 4.4 のタグクラウド対応

2016年1月31日 0 開発 ,

このブログをホストしている WordPress を 4.4 に更新したら、サイドバーで表示しているタグクラウドにスタイルが反映されなくなった。

調べてみると widget_tag_cloud_args の仕様変更が原因らしい。

修正するには自前の widget_tag_cloud_args 関数で返す値を、標準値と結合する必要がある。

function mytheme_widget_tag_cloud_args( $args )
{
    $args = array(
        'unit'     => 'em',
        'number'   => 20,
        'smallest' => 0.8,
        'largest'  => 0.8
    );

    return $args;
}
add_filter( 'widget_tag_cloud_args', 'mytheme_widget_tag_cloud_args');

これを以下のように修正する。

function mytheme_widget_tag_cloud_args( $args )
{
    $args = wp_parse_args( $args, array(
        'unit'     => 'em',
        'number'   => 20,
        'smallest' => 0.8,
        'largest'  => 0.8
    ) );

    return $args;
}
add_filter( 'widget_tag_cloud_args', 'mytheme_widget_tag_cloud_args');

WordPress で動作に関わる部分の変更は滅多にないこと、記事を投稿するときにそれ自体はチェックするがトップページはあまり見ない ( 現在のテーマではトップだけサイドバー表示している ) ことから、気づくのが遅れてしまった。

この修正と、iOS Safari の慣性スクロールに対応するため -webkit-overflow-scrolling を有効にしたテーマをリリースした。

ブログには既に反映している。