Asial Blog

Recruit! Asialで一緒に働きませんか?

DoCoMo向けにCSS指定をインラインに埋め込むPHPライブラリ「toInlineCSSDoCoMo」作りました

カテゴリ :
バックエンド(プログラミング)
タグ :
Tech
PHP
携帯
CSS
こんにちは。Windowsの最大の発明はゴミ箱の標準装備だと思っている亀本です。
追記:Mac信者の某氏にゴミ箱はWindowsの発明じゃないと突っ込まれてしまいました。すみません<(。_。)>


昨日はグリーさんのオープンソース勉強会に参加してきました。
今回の講師はDeNAの川崎さんで、わりとモバイル屋さんな自分としてはぜひともチェックしておきたいなと思って参加してきました。
勉強会・懇親会ともなかなか面白い話が聞けたり、変な人がいっぱいしたりしてとても面白かったです。


モバイルをやっているといつも面倒なのは、テンプレートの扱いです。
そのあたりのまとめは以前このブログでうちの高橋さんが超まとめてくれた記事があるので、そちらをご参照ください。

とくにDoCoMoのCSS(i-CSS)は開発者泣かせですね。インラインのみに対応とか、開発しにくくて涙ちょちょぎれそうです。

さてさてそんなDoCoMoのCSSですが、PerlにはHTML::DoCoMoCSSというCPANライブラリがあります。
styleタグで指定した外部CSSファイルを読み込んで、インラインのstyle要素に入れ込んでくれるというすぐれものです。

(MobaSiFもそうですが、Perlの周辺はモバイル関連のライブラリが非常に充実していますね。
なんだかあちこち探してみると、いろいろと便利そうなライブラリが転がっています。)


せっかくそんな素晴らしいライブラリがあるんですが、僕はPerl?イエモンですね、把握しました。みたいな生粋のPHPerなので、PHPしか使えません。
PerlなんてわかんないよPHPじゃないと使えないよ(´・ω・`)ショボーンって思ったので、これをPHPで作ってみました。

ファイル:toInlineCSSDoCoMo.tar.gz
(追記2008/07/09 18:19:getInstance()にstatic指定が抜けていたので修正しました)

追記:バージョンアップした物をHTML_CSS_Mobileという名称に変更して、CodeReposにimportしました。
http://coderepos.org/share/browser/lang/php/HTML_CSS_Mobile


同梱物は
  1. toInlineCSSDoCoMo/
  2. + lib/
  3. ++ toInlineCSSDoCoMo.php
  4. ++ selectorToXPath.php
  5. + sample/
  6. ++ sample.php
  7. ++ sample.html
  8. ++ sample.css
です。

toInlineCSSDoCoMo.phpは、基本的にはid:tokuhiromさんの作った上記のHTML::DoCoMoCSSをPHP用にリライトしたもので、それに若干の機能追加をしています。

selectorToXPath.phpもPerlのHTML::Selector::XPathというid:miyagawaさんのライブラリの移植です。
ただ、selectorToXPathの方は自分自身がXPathもCSSもさほど詳しくなかったので、理解できるレベルでしか移植していません。なので単体での配布はちょっと見送りましたが、大体の場合はうまく動くと思います。

なお、動作環境としてはPHP 5.1以上になります。


以下に簡単に利用方法を説明しておきます。

このライブラリ自体がPEAR::HTML_CSSに依存しているので、まずそちらをインストールします。
  1. % sudo pear install HTML_CSS
あとは、上記のtarボールをDLしてきて、普通に展開して下さい。
  1. % wget http://blog.asial.co.jp/data/toInlineCSSDoCoMo.tar.gz
  2. % tar xvzf toInlineCSSDoCoMo.tar.gz

サンプルスクリプトは以下のようになります。
  1. <?php
  2. require_once 'lib/toInlineCSSDoCoMo.php';
  3.  
  4. $document = file_get_contents('path/to/file.html');
  5. try {
  6.     echo toInlineCSSDoCoMo::getInstance()->setBaseDir('path/to/css_basedir/')->apply($document);
  7. } catch (Exception $e) {
  8.     var_dump($e);
  9. }
これで、linkタグで外部ファイルとして指定してあるCSS、および<style>タグで記述したCSSをパースして、よしなにインラインのstyle要素に埋め込んでくれます。

なお、CSSはhttp経由で取ってくるわけじゃないので、ちゃんとcss_basedirをパス指定してあげてください。

実際にどんな感じになるかは、sampleディレクトリの中を見てもらえればわかりやすいかと思いますが、

sample.html
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-transitional.dtd">
  2. <html lang="ja">
  3. <head>
  4.   <link rel="stylesheet" href="sample.css" />
  5.   <style type="text/css">
  6. div.hoge {
  7.   color:#00FF00;
  8. }
  9. div.hoge a { 
  10.   color:#FFFF00;
  11. }
  12.   </style>
  13. </head>
  14. <body>
  15. <h1>test</h1>
  16.  
  17. <div>hogehoge</div>
  18. <div class="hoge">test<a href="" style="font-size:8px">test</a></div>
  19.  
  20. </body>
  21. </html>

sample.css:
  1. body {
  2.   margin: 0px;
  3. }
  4. h1 {
  5.   font-size: 11px;
  6. }
  7.  
  8. div {
  9.   font-size: 10px;
  10. }
  11.  
  12. a:hover {
  13.   color: #0000FF;
  14. }

結果:
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml-transitional.dtd">
  2. <html lang="ja">
  3. <head><style type="text/css"><![CDATA[
  4. a:hover{color:#0000FF;}
  5. ]]></style></head>
  6. <body style="margin:0px;">
  7. <h1 style="font-size:11px;">test</h1>
  8.  
  9. <div style="font-size:10px;">hogehoge</div>
  10. <div class="hoge" style="font-size:10px;color:#00FF00;">test<a href="" style="font-size:8px;color:#FFFF00;">test</a>
  11. </div>
  12.  
  13. </body>
  14. </html>

という感じになります。


現段階で実装してあること:
・linkタグで指定した外部CSSの読み込み、インライン化
・ファイル内のstyleタグCSSの読み込み、インライン化
・インライン化したlinkタグやstyleタグの削除
・a:hover,a:link,a:visited,a:focusのstyleタグへの埋め込み
・複数class指定への対応

まだ対応していないこと:
・@importなどの対応
・a:以外の疑似クラスにもうちょっときちんと対応


こんな感じのライブラリです。
これでDoCoMoのCSSをインライン以外でも書けるようになるので、テンプレート作成がだいぶ楽になるんじゃないかなー、と思います。
もしお役に立てば幸いです。

なお、このライブラリを完成させるにあたり、id:maru_ccさん、うちの会社の(笑)熊谷さんにはデバッグ、アイデア出し等でひじょーにお世話になりました。
この場をお借りしてお礼申し上げます。


※おまけですが、selectorToXPathの使い方はこんな感じです。
  1. <?php
  2. require_once 'lib/selectorToXPath.php';
  3.  
  4. $selector = 'li.hogehoge';
  5.  
  6. $xpath = selectorToXPath::toXPath($selector);
  7.  
  8. var_dump($xpath);
たぶん、これはこれ単体で結構使えると思うので、問題なさそうなら単体配布しようかなー。。。なんて。