#!/bin/bash
#new timeout=30
# 次の行を htmllint のパスに設定する。(*1)
lint_path='/Applications/Utilities/htmllint_folder/htmllint'
# 必要なら、次の行に htmllint に渡すオプションを与える。(*2)
lint_options='-d form-tabindex,form-accesskey,xhtml-emptytag'
########################################################################
# Another HTML lint を利用して HTML 構文をチェックする mi 用シェルスクリプト。
# 上の timeout に制限時間(秒)を記述する(長大な文書だと長くする必要有り)。
# 当然だが Another HTML lint をダウンロードしてインストールする必要がある:
# http://openlab.ring.gr.jp/k16/htmllint/
# (*1) 上ではアプリケーション:ユーティリティフォルダ内の htmllint_folder 内
# を指定している。
# 【注意】パスに日本語等やシングルクオート(')が含まれていると
# 動作しない。また、等号(=)の両隣に空白を挿入してはいけない。)
# 【注意】「アプリケーション」や「ユーティリティ」という名前は
# ローカライズされた表示用の名称であり、シェルでは「本当の」パスにしておく必要がある。
# 本当のパスは情報ウインドウで調べられる。
# (*2) オプションの詳細は htmllint 付属の文書を参照。
# 上では、フォーム要素に tabindex, accesskey 属性が指定されていなくても、
# あるいは、HTML の空要素が スペース+「/>」で閉じられていても、
# 警告を出さないようにしている。
# このツールの利用にあたって必要な設定はここまで。以下はプログラムコード。
########################################################################
# htmllint の存在をチェック。
if ! test -a "$lint_path"
then echo 'htmllint の場所が指定されていないか、指定されたパスに日本語等が含まれています。このツールを編集して htmllint へのパスを指定して下さい。
オプションキーを押しながらこのツールを起動すると編集できます。'
exit
fi
# 保存されていない新規文書かどうかをチェック
if test -z "$1"
then echo '実行前に文書を保存する必要があります。保存するファイル名には半角の英字/数字/記号( * ¥ / を除く)のみを利用する必要があります。'
exit
fi
# bash 文字列マッチング拡張
shopt -s extglob
# ファイルのパスからファイルの存在するディレクトリパスとファイル名を得る
dir_path=${1%%+([^/])}
file_name=${1##/*/}
has_illegal_chars="${file_name##+([ -~])}${file_name##+([^¥*])}"
# bash 文字列マッチング拡張を切る(不要な機能はなるべく使わない)
shopt -u extglob
#ファイル名チェック (*3)
if test $has_illegal_chars
then echo 'ファイル名に半角英数記号(ASCII 文字)でない文字や、特殊文字 * や ¥ が含まれています。htmllint が正しく動作しない可能性があるので、ファイル名にはこれらの文字を含めない必要があります。'
exit
fi
# カレントディレクトリを文書が存在するディレクトリにする (*3)
cd "$dir_path"
if test $? != 0
then echo 'ファイルの存在するディレクトリに移動(cd)できませんでした。'
exit
fi
# htmlint 実行 (*4)
perl "$lint_path" $lint_options "$file_name" | iconv -c -f EUC-JP -t UTF-8
error=$?
if test $error != 0
then echo "実行エラー(コード $error)"
exit
fi
# ファイルパス出力。(*5)
echo '
ファイルパス:'
echo "$1" | iconv -c -f UTF8-MAC -t UTF-8
# (*3) htmllint は EUC-JP で引数のファイルパスを認識しているようだ。
# 一方シェルでは UTF-8 がデフォルトの文字コードなので、日本語等が
# パスに含まれていると、文字コードの違いからうまくファイルを認識してくれない。
# そこで、cd コマンドでいったんファイルの存在するディレクトリに移動してから
# htmllint を実行することにすれば、引数はファイルの絶対パスでなく、
# ファイル名のみで済み、親ディレクトリまでのパス内に日本語等が含まれていても
# 正常に処理される。ただし、ファイル名自体に日本語があるときは不可。
# また、htmllint は引数のファイル名に「*」が含まれていると、ワイルドカードと
# 見なしてしまう。このスクリプトの目的には適合しないので、この場合もはじく。
# (*4) htmlint の出力文字エンコーディングは EUC-JP であり、
# シェルのデフォルトの出力文字エンコーディング UTF-8 と異なる。
# おそらく mi は UTF-8 の出力を期待していると思われるので、
# iconv コマンドを利用してエンコーディングを変換している。
# (自動判別しているようだが、EUC-JP のままだと文字化けすることが多い)
# 他のメッセージ等の出力と混在させるときにも、こうした方が好都合になる。
# (*5) OSX のファイルシステムで使われている文字コードは NFD 形式と呼ばれる、
# 「正規化された」Unicode (UTF-8) が利用されている。文字「ぶ」は「ふ」と「゛」
# といった具合に、濁音やアクセント記号などの合成可能文字が分解されている。
# 参照:
# http://developer.apple.com/ja/qa/qa2001/qa1235.html
# http://homepage1.nifty.com/nomenclator/unicode/normalization.htm
# http://developer.apple.com/technotes/tn/tn1150.html
# 多くの環境やプログラムにおいて一般的な通常の(合成済みの) UTF-8 と解釈して
# 表示すると、これらの濁点やアクセント記号が抜けてしまう上に、他の出力の
# 文字化けも誘発するようだ。
# つまり、濁点つきの仮名文字などを含んだファイルパスをそのまま出力させると、
# 合成済みの UTF-8 を期待している出力プログラムでは、おかしな表示になる。
# (この場合、 mi の文字コード自動判別がうまくいかなくなる。)
# その対策は、出力前に iconv コマンドで合成済みの UTF-8 に変換することだ。
# 何故ファイルシステムをこの様な特殊な仕様にしたのだろうか?
# おそらく Finder で名前順にファイルを整列させるときに、例えば
# 名前が「は」で始まるファイルの直後に「ば」で始まるファイルが続くように
# 整列させるには、分解された形式の方が自然に処理できるからだと思われる。
# ノート:OSX のシェルのデフォルトエンコーディングと改行コードは
# UTF-8, LF なので、このスクリプト自体の文字コードも UTF-8 にしている
#(コメント内の文字が誤って解釈されることを避ける)。