ようこそゲストさん

matuダイアリー

2008/09/16(火) adiaryでシンタックス・ハイライト

はてブ情報 はてブに登録 はてブ数 adiary matu
外部ライブラリ(JavaScript)を使用するので、"adiaryで"とか書いてしまうと、半ば釣りと思われるかもしれませんが、気にせず参ります(笑)
できるだけシステム的な変更はなしで、外部ライブラリを使用してシンタックスハイライトを実現する方法を検討してみました。(少ないですけど)
adiaryで、実装だけしてあって、特に利用することのない>|filetype|~||<記法をうまく使ってやりたいなと思います。

google-code-prettifyで解決

これを利用するのが最速っぽいです。言語名を指定しなくても、勝手にキーワードをハイライトしてくれるので、使い勝手は良いです。また、スケルトンだけで対応できるのでシステムの変更に強く、導入が楽です。
20080916-gcp.JPG
  1. /path/to/adiary/diary.skel/_frame.htmlを/path/to/adiary/diary.user.skelにコピーします。
    以後は/path/to/adiary/diary.user.skel下の_frame.htmlを編集します。
  2. こちらのページからprettify-small-***.zipをダウンロードし、適当なディレクトリに展開します。
    私は/adiary/prettifyに入れました。
  3. 以下のコードを_frame.htmlのヘッダ部に挿入します。
    <link type="text/css" rel="stylesheet" media="all" href="<@Basepath>prettify/prettify.css">
    <script type="text/javascript" src="<@Basepath>prettify/prettify.js"></script>
    <script type="text/javascript"><!--
      (function(onload){
            if (window.addEventListener) {
                    window.addEventListener('load', onload, false);
            } else if (window.attachEvent){
                    window.attachEvent('onload',  onload, false);
            } else {
                    window.onload = onload;
            }
      })(function(){
                    var pre = document.getElementsByTagName('pre');
                    for (var n = 0; n < pre.length; n++) {
                                    if ( pre[n].className === 'syntax-highlight' )
                                      pre[n].className=pre[n].className + ' prettyprint';
                    }
                    prettyPrint();
      });
     --></script>
    
これで完了です。あとは、記事を作成する際に
 >|ruby|
 module English
   def hello
     puts "Hello"
   end
   module_function :hello
 end
 
 English.hello
 ||<
などと書けば、ハイライトされます。(若干地味ですね。)
filetype(ここではruby)の部分は、google-code-prettifyはfiletype(言語名)を意識しないので、なんでもいいです。hogeとかfooとかでも。
わざわざ、filetypeを指定したくない場合は、挿入したコード中の
if ( pre[n].className === 'syntax-highlight' )
を削除すればOKですが、すべてのpreタグがハイライト化の対象になってしまうので、あまりよろしくないです。

SHJSで解決

もう一つは、SHJSでの対応法を。こちらは、言語ごとにjs、cssファイルがメンテできたり、表示がきれいだったりします。ただ、ほんのちょっとシステム的な変更もしなければいけません。
20080916-shjs.JPG
  1. /path/to/adiary/diary.skel/_frame.htmlを/path/to/adiary/diary.user.skelにコピーします。
    以後は/path/to/adiary/diary.user.skel下の_frame.htmlを編集します。
  2. こちらのページからshjs-***.zipをダウンロードし、適当なディレクトリに展開します。
    私は/adiary/shjsに入れました。
  3. /path/to/adiary/lib/Satsuki/TextParser/Satsuki.pmを修正します。
    if ($line =~ /^>\|(\w+)\|/) { $new_block_end = '||<'; $block_tag='pre'; $p=$tag=$atag=0; $dc="syntax-highlight"; }
    
    の部分を
    if ($line =~ /^>\|(\w+)\|/) { $new_block_end = '||<'; $block_tag='pre'; $p=$tag=$atag=0; $dc="$1"; }
    
    に修正します。
  4. 以下のコードを_frame.htmlのヘッダ部に挿入します。
    <link type="text/css" rel="stylesheet" media="all" href="<@Basepath>shjs/sh_style.css">
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_bison.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_changelog.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_cpp.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_csharp.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_css.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_diff.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_flex.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_html.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_java.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_javascript.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_latex.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_log.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_m4.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_makefile.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_oracle.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_pascal.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_perl.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_php.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_prolog.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_python.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_ruby.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_sh.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_sql.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_tcl.min.js"></script>
    <script type="text/javascript" src="<@Basepath>shjs/lang/sh_xml.min.js"></script>
    
    <script type="text/javascript"><!--
      (function(onload){
            if (window.addEventListener) {
                    window.addEventListener('load', onload, false);
            } else if (window.attachEvent){
                    window.attachEvent('onload',  onload, false);
            } else {
                    window.onload = onload;
            }
      })(function(){
                    sh_highlightDocument();
      });
     --></script>
    
    これは、すべてのJavaScriptをロードする欲張りバージョンですが、ロードだけでものすごく時間がかかるので、使いそうな言語だけに絞ってロードした方が良さそうです。
手順としては以上で完了です。あとは記事を書く際に
 >|sh_ruby|
 module English
   def hello
     puts "Hello"
   end
   module_function :hello
 end
 
 English.hello
 ||<
などと書けば、ハイライトされます。
filetype(ここではsh_ruby)の部分は、こちらをご参照ください。基本的にsh_言語名です。
これは、adiaryの>|filetipe|~||<記法が<pre class="syntax-highlight">~</pre>で展開されることと、SHJSのUsageが<pre class="sh_xxxx">~</pre>ということで、比較的楽に導入できそうということで試してみました。

他には?

あなたのソースコードを彩る、Syntax Highlighterまとめ - Blog.37to.netがよくまとまっています!
ほかにも使い勝手のよいライブラリがあるのかもしれません。
以前のはてなのようにText::VimColorなどを利用すれば、adiaryでもシステム的に対応できそうな気はしますが…。そんなに使用頻度ないしなぁ(笑

名前:  非公開コメント   

URL(任意):
  • TB-URL  http://d.matu.biz/040/tb/

2008/09/16(火) asin記法をカスタマイズ2

はてブ情報 はてブに登録 はてブ数 adiary matu
再編集・再構築時に外部接続のコストがかかることから、このカスタマイズは使用しなくなりました。

asin記法をカスタマイズ - matuダイアリーでasin記法で詳細オプションを指定したときのカスタマイズを行いましたが、あまりにbuggyだったのと、スタイルをベタ書きしすぎていたのが気になったので修正しました。
  • バグ修正
    • Authorが複数じゃなかったり、存在しなかった場合はエラーを吐きまくってました。お恥ずかしい。
  • 出力するHTMLタグを、(ほぼ)はてな化。
    • はてなテーマに定義されている、asin系のスタイルがそのまま使えるのがメリット。

出力例

試しに、いままで紹介させていただいた商品をasin記法の詳細オプション付きで表示すると、以下のようになります。
[asin:4569701620:detail]
[asin:B00111O8YQ:detail]
[asin:487311375X:detail]
200809asin-detail.jpg
といった具合に、メディアによって表示する情報数がまちまちなので、たとえばDVDだったら出演者や監督名などを表示するかといったところが今後の検討課題です。

今回の修正内容

 --- Tag_amazon.pm.orig  2008-02-07 01:50:00.000000000 +0900
 +++ Tag_amazon.pm       2008-09-16 08:53:28.000000000 +0900
@@ -1,4 +1,7 @@
 use strict;
 +use WebService::Simple;
 +use Encode;
 +
 #------------------------------------------------------------------------------
 # Amazon記法プラグイン
 #                                                   (C)2006 nabe / nabe@abk.nu
@@ -82,6 +85,12 @@
                $asin .= $sum;
        }

 +
 +       # Asin Detail
 +        if ( $ary->[0] eq 'detail') {
 +               return &amazon_asin_detail($asin, $asid);
 +       }
 +
        # 画像モード?
        if ($ary->[0] eq 'img' || $ary->[0] eq 'image' || $ary->[0] eq 'detail') {
                shift(@$ary);
@@ -124,5 +133,61 @@
        return "<a href=\"http://www.amazon.co.jp/exec/obidos/ASIN/$asin/$asid\"$attri><img src=\"http://images-jp.amazon.com/images/P/$asin$size\" alt=\"$name\" class=\"asin\"$size_tag></a>";
 }

 +sub amazon_asin_detail {
 +       my ($asin, $asid) = @_;
 +
 +       my $amazon = WebService::Simple->new(
 +               base_url => "http://webservices.amazon.co.jp/onca/xml",
 +               param    => {
 +                       AssociateTag   => $asid,
 +                       SubscriptionId => '0EFZW5XNGVAC9H12ER82',
 +                       Service        => 'AWSECommerceService',
 +                       locale         => 'jp',
 +                       ContentType    => 'text/xml',
 +                       Version        => '2007-10-29',
 +               }
 +       );
 +
 +       my $resp = $amazon->get({
 +               Operation     => 'ItemLookup',
 +               ItemId        => $asin,
 +               ResponseGroup => 'Medium',
 +       });
 +
 +       my $item = $resp->parse_response->{Items}->{Item};
 +       my $url    = $item->{DetailPageURL};
 +       my $img    = $item->{MediumImage}->{URL};
 +       #my $img    = $item->{SmallImage}->{URL};
 +       my $title  = $item->{ItemAttributes}->{Title};
 +       my $price  = $item->{ItemAttributes}->{ListPrice}->{FormattedPrice};
 +       my $media  = $item->{ItemAttributes}->{Binding};
 +       my $author;
 +       if ( ref($item->{ItemAttributes}->{Author}) eq 'ARRAY' ) {
 +               $author = join(", ", @{$item->{ItemAttributes}->{Author}});
 +       } else {
 +               $author = $item->{ItemAttributes}->{Author};
 +       }
 +       my $maker  = $item->{ItemAttributes}->{Manufacturer};
 +       my @html = ();
 +
 +       push(@html, "<div class=\"hatena-asin-detail\">\n");
 +       # image
 +       push(@html, "<a href=\"$url\"><img src=\"$img\" class=\"hatena-asin-detail-image\" alt=\"$title\" title=\"$title\"></a>\n");
 +       # info
 +       push(@html, "<div class=\"hatena-asin-detail-info\">\n");
 +       push(@html, "<p class=\"hatena-asin-detail-title\"><a href=\"$url\">$title</a></p>\n");
 +       push(@html, "<ul>\n");
 +       push(@html, "<li>$media</li>\n") if ($media);
 +       push(@html, "<li>$author</li>\n") if ($author);
 +       push(@html, "<li>$maker</li>\n") if ($maker);
 +       push(@html, "<li>$price</li>\n") if ($price);
 +       push(@html, "</ul>\n");
 +       push(@html, "</div>\n");
 +       push(@html, "<div class=\"hatena-asin-detail-foot\"></div>\n");
 +       push(@html, "</div>\n");
 +
 +       @html = Encode::encode('utf8',"@html");
 +       return "@html";
 +}

 1;

名前:  非公開コメント   

URL(任意):
  • TB-URL  http://d.matu.biz/039/tb/
Related Posts with Thumbnails