2008/07/31

Blogger Slippy Map

[ja] Slippy Map MediaWiki Extensionからの出力を基にBlogger用のSlippy Mapウィジェットを作成しました。
divタグに幾つかの属性値を設定して使用します(使用例をご覧下さい)。
ウィジェットを追加するには下のボタンを押して下さい。
Firefox3とSafari3では動きますが、IE6では動きませんでした。
Firefox3、Safari3、IE6で動きました。

[en] I made a Slippy Map widget based on output from Slippy Map MediaWiki Extension.
Usage is just adding some attributes to div tag; see examples below.
To get this widget, click the button.
It works on Firefox3 and Safari3, doesn't work on IE6.
It works on Firefox3, Safari3 and IE6.






使用例 (Examples)




<div class="slippymap" lat="36" lon="139" z="3" style="width:250px;height:200px;"></div>






<div class="slippymap" lat="52.516" lon="13.378" z="9" style="width:300px;height:300px;"></div>






<div class="slippymap" lat="51.5012" lon="-0.123" z="14" style="width:500px;height:400px;"></div>





履歴 (History)

0.1
2008-07-31 新規作成。Firefox3とSafari3で動作。
0.1.1
2008-08-02 IE6で動作。

Slippy Mapのウィジェットを作ってみる

Blogger上でSlippy Mapを一応表示できるようになったので、ウィジェットとして作ってみることにしました。

前回は「地図作成時のオブジェクト名」と「地図描画スペースとなるdiv要素のid」が共に"map"だったので、1ページに複数のSlippy Mapを表示させるには、この組み合わせ毎にユニークにしてあげればいっかなーと考えていましたが、普段からJavaScriptなどをやり慣れていない私にはそれほど単純ではありませんでした。


とりあえずコードを書いて1ページに複数のSlippy Mapを表示させようとすると、前回のSlippy Mapを含めて、どれか1つしかタイルが読み込まれませんでした。コードと睨めっこしても他にユニークにするべきところも無さそうだしJavaScript自体は動いているので、もしかしたらOpenLayersの制約かななどと思いながらコードを眺めていると、window.onload=init; と書かれた行が目に留まりました。色々検索しているうちに次のページが見付かったので参考にさせてもらいました。



単純に window.onload を使わないようにコードを修正すると、1ページに複数のSlippy Mapを表示させることができるようになりましたが、よーっく地図を見ると全て同じ座標とズームレベルになっています。地図そのもののオブジェクトだけでなく、座標とズームレベルのオブジェクトも別の名前で作ってあげないと駄目みたいですね...

このウィジェットの追加ボタンのページを作成して、そちらに簡単な使用例を載せておきます。

現時点のコード(一応完成版)はこちら。( "+ expand source" のリンクをクリックして下さい。)
<style>
.slippymap img { padding: 0px !important; border: none !important;}
</style>
<!-- bring in the OpenLayers javascript library -->
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<!-- bring in the OpenStreetMap OpenLayers layers. Using this hosted file will make sure we are kept up to date with any necessary changes. -->
<script src="http://openstreetmap.org/openlayers/OpenStreetMap.js"></script>

<script type="text/javascript"><!--
// Blogger Slippy Map 0.1
var i = 0;
var lat = 54;
var lon = 0;
var z = 4;
var style = "width:300px; height:200px;";
var element1, element2, element3, text;
var tags = document.getElementsByTagName("div");

  for ( var j=0; j < tags.length; j++ ) {

    if ( tags[j].className == "slippymap" ) {

      i++;

      if ( tags[j].getAttribute("lat") ) {
         lat = tags[j].getAttribute("lat");}
      if ( tags[j].getAttribute("lon") ) {
         lon = tags[j].getAttribute("lon");}
      if ( tags[j].getAttribute("z") ) {
         z = tags[j].getAttribute("z");}
      if ( tags[j].getAttribute("style") ) {
         style = tags[j].getAttribute("style");}

      element1 = document.createElement("script");
      element1.setAttribute("type","text/javascript");
      text = document.createTextNode("var lat"+ i + "=" + lat + "; var lon"
        + i + "=" + lon + "; var zoom"+ i + "=" + z + "; var map" + i
        + "; function lonLatToMercator(ll) { var lon = ll.lon * 20037508.34 / 180; "
        + "var lat = Math.log (Math.tan ((90 + ll.lat) * Math.PI / 360)) / "
        + "(Math.PI / 180); lat = lat * 20037508.34 / 180; return new "
        + "OpenLayers.LonLat(lon, lat); } ;"
        + "if (typeof window.addEventListener == 'function') { "
        + "window.addEventListener('load', init, false);} else if (typeof "
        + "window.attachEvent == 'object') { window.attachEvent('onload', "
        + "init);} else { var oldonload = window.onload ; if (typeof "
        + "window.onload != 'function') { window.onload = init;} else { "
        + "window.onload = function() { oldonload(); init(); } } };"
        + "function init() { map" + i + " = new OpenLayers.Map('map" + i 
        + "', { controls:[ new OpenLayers.Control.Navigation()"
        + ", new OpenLayers.Control.PanZoom(), new OpenLayers.Control"
        + ".LayerSwitcher()], maxExtent: new OpenLayers.Bounds(-20037508.34, "
        + "-20037508.34, 20037508.34, 20037508.34), maxResolution:156543.0399, "
        + "units:'meters', projection: 'EPSG:900913' } ); var mapnik = new "
        + "OpenLayers.Layer.OSM.Mapnik('Mapnik'); map" + i + ".addLayer(mapnik);"
        + " var osmarender = new OpenLayers.Layer.OSM.Osmarender('Osmarender'); "
        + "map" + i + ".addLayer(osmarender); var cyclemap = new OpenLayers"
        + ".Layer.OSM.CycleMap('Cycle Map'); map" + i + ".addLayer(cyclemap); "
        + "var maplint = new OpenLayers.Layer.OSM.Maplint('Maplint'); map" + i 
        + ".addLayer(maplint); var lonLat" + i + " = lonLatToMercator(new "
        + "OpenLayers.LonLat(lon" + i + ", lat" + i + ")); map" + i 
        + ".setCenter (lonLat" + i + ", zoom" + i + "); } ");
      element1.appendChild(text);
      tags[j].appendChild(element1);
      element1 = document.createElement("div");
      element1.setAttribute("class","tempmap");
      element1.setAttribute("style","margin-bottom:-35px;");
      <!-- define a DIV into which the map will appear -->
      element2 = document.createElement("div");
      element2.setAttribute("id", "map" + i);
      element2.setAttribute("style", style 
        + " border-style:solid; border-width:1px; border-color:#000;");
      element1.appendChild(element2);
      element2 = document.createElement("br");
      element1.appendChild(element2);
      element2 = document.createElement("span");
      element2.setAttribute("class","tempmap")
      element2.setAttribute("style",
        "font-size:70%; background-color:white; position:relative;top:-65px;left:5px;z-index:1003;");
      text = document.createTextNode("Data by ");
      element2.appendChild(text);
      element3 = document.createElement("a");
      element3.setAttribute("href","http://www.openstreetmap.org/?lat=" + lat 
        + "&lon=" + lon + "&zoom=" + z );
      element3.setAttribute("title","See this map on OpenStreetMap.org");
      text = document.createTextNode("OpenStreetMap");
      element3.appendChild(text);
      element2.appendChild(element3);
      element3 = document.createElement("br");
      element2.appendChild(element3);
      element3 = document.createElement("a");
      element3.setAttribute("href","http://creativecommons.org/licenses/by-sa/2.0/");
      element3.setAttribute("title","Creative Commons Attribution-Share Alike 2.0");
      text = document.createTextNode("CC-BY-SA-2.0");
      element3.appendChild(text);
      element2.appendChild(element3);
      element1.appendChild(element2);
      tags[j].appendChild(element1);
    }
  }
--></script>

Slippy Mapを表示してみる

OpenStreetMapではサイトに表示しているメインの地図をSlippy Mapと呼んでいます。

最近、日本語サイトのOpenStreetMap Japan地図ページの改良をなさっている方が居て、私もちょっと触ってみたくなってBloggerに表示させてみることにしました。


ベースにしたのは、MediaWiki用のSlippy Map MediaWiki Extensionからの出力です。

サーバーからタイル(細分化された地図画像)を引っ張ってくることは直ぐにできましたが、タイル同士の間に数ピクセルの隙間が空いてしまいます。OSM.orgやOSM.jpで使用しているコードを覗いて見たり、OpenLayersの文書やソースを読んでみても解決できず二日程悩んでいました。ふと思い立ってFirefoxのアドオンのページを確認してみるとFirebugのFirefox3対応版が出ていたので早速インストール。HTMLを調査すると適用されているスタイル (padding:4px;) や要素のクラス名 (olTileImage) が簡単に分かり、直ぐに解決。この程度のことだから、OpenLayersのFAQやメーリングにも質問が出ていなかったんだと思いました。それにしてもFirebugは便利だなぁ。あまり使ったことがないので、使い方も良く分かんないけど...

やろうと思ったけどやり方が分からず、とりあえず現時点では諦めたこと。
  • 地図のスクロール時やズーム時に、OSM.orgの地図へのURLに入っている座標やズームレベルを更新すること。
    • URLのベースをOSM.orgサーバーへ向ける。
    • 座標の形式を lat=35.67255 lon=139.76183 のように普段GPSなどで見ているものと同じにする。
    • リンクテキストを Permalink 以外のものにする
  • ズームレベルに合わせたスケールを表示する。
これからやろうと思っていること。



上の地図を表示させているコードはこちら。( "+ expand source" のリンクをクリックして下さい。)
<style>
.map img { padding: 0px !important; border: none !important;}
</style>

<div class="map" style="margin-bottom:-35px;">

<!-- define a DIV into which the map will appear -->
<div style="width:400px; height:350px; border-style:solid; border-width:1px; border-color:#000;" id="map"></div>

<br/>
<span style="font-size:70%; background-color:white; position:relative;top:-65px;left:5px;z-index:1003;">Data by <a href="http://www.openstreetmap.org/?lat=36&lon=139&zoom=4" title="See this map on OpenStreetMap.org">OpenStreetMap</a><br/>
<a href="http://creativecommons.org/licenses/by-sa/2.0/" title="Creative Commons Attribution-Share Alike 2.0">CC-BY-SA-2.0</a></span>

</div>

<!-- bring in the OpenLayers javascript library -->
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<!-- bring in the OpenStreetMap OpenLayers layers. Using this hosted file will make sure we are kept up to date with any necessary changes. --> 
<script src="http://openstreetmap.org/openlayers/OpenStreetMap.js"></script> 

<script type="text/javascript"> 
var lon=139; 
var lat=36; 
var zoom=4; 
var map; 

function lonLatToMercator(ll) {
  var lon = ll.lon * 20037508.34 / 180;
  var lat = Math.log (Math.tan ((90 + ll.lat) * Math.PI / 360)) / (Math.PI / 180);
  lat = lat * 20037508.34 / 180;
  return new OpenLayers.LonLat(lon, lat);
}

window.onload=init; 

function init() {
  map = new OpenLayers.Map("map", {
    controls:[
      new OpenLayers.Control.Navigation(),
      new OpenLayers.Control.PanZoom(),
      new OpenLayers.Control.LayerSwitcher()],
    maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
    maxResolution:156543.0399,
    units:'meters',
    projection: "EPSG:900913"
  } );
  var mapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
  map.addLayer(mapnik);
  var osmarender = new OpenLayers.Layer.OSM.Osmarender("Osmarender");
  map.addLayer(osmarender);
  var cyclemap = new OpenLayers.Layer.OSM.CycleMap("Cycle Map");
  map.addLayer(cyclemap);
  var maplint = new OpenLayers.Layer.OSM.Maplint("Maplint");
  map.addLayer(maplint);
  var lonLat = lonLatToMercator(new OpenLayers.LonLat(lon, lat));
  map.setCenter (lonLat, zoom);
} 
</script>


追記

Widget追加ボタンを作成しました。
尚、上のコードで表示できるSlippy Mapは1ページに1つだけで、Widgetでは複数のSlippy Mapを同じページに表示できます。また、上のコードによるSlippy Mapと同じページ内にWidgetによるSlippy Mapがあると、その影響により指定した座標・ズームで表示できないことがあるようです。

2008/07/28

HaloScanでトラックバック

クリボウの Blogger Tipsを読んで、HaloScanのトラックバック機能を付けてみました。


HaloScanのアカウント作成後、ログインし直してInstallation Instructionsの画面に入ると、まず使っているブログの種類を選択します。自分の場合は Blogger or Blogspot (New Version / Google Login) なので、それを選択して手順通りにやってみましたが、HaloScan側で更新したテンプレートをBloggerにアップロードするところでエラーになり上手く行きませんでした。試しに、Blogger or Blogspot (Old Version)None of the Above / Manual を選択して、それらの手順もやってみましたが、別のエラーで上手く行きませんでした。

で、結局、Bloggerの [レイアウト] → [HTMLの編集] → 「テンプレートを編集」で「ウィジットのテンプレートを展開」にチェックを付け、エディタで開いた最初のHaloScan側で更新したテンプレートと睨めっこをしながら手作業で更新部分を編集してみたところ、やっと動くようになりました。

更新部分は3箇所で、今は下のようになっています。(HaloScan側で削除された部分はコメント化してあります。)

<!-- START comment out for haloscan (part 1)
            <a class='comment-link' expr:href='data:post.addCommentUrl' expr:onclick='data:post.addCommentOnclick'><b:if cond='data:post.numComments == 1'>1 <data:top.commentLabel/><b:else/><data:post.numComments/> <data:top.commentLabelPlural/></b:if></a>
END comment out for haloscan (part 1) -->
<!-- start haloscan (part 1) -->
            <script src='http://www.haloscan.com/load/tatata7' type='text/javascript'> </script>
<span class='post-comment-link'>
<a class='comment-link' expr:href='"http://www.haloscan.com/comments/tatata7/" + data:post.id + "/"' expr:onclick='"HaloScan(" + "\""+ data:post.id + "\"" + ");return false;"'>
<script type='text/javascript'>postCount('<data:post.id/>');</script>
</a> | 
<a class='comment-link' expr:href='"http://www.haloscan.com/tb/tatata7/" + data:post.id + "/"' expr:onclick='"HaloScanTB(" + "\""+ data:post.id + "\"" + ");return false;"'>
<script type='text/javascript'>postCountTB('<data:post.id/>');</script>
</a>
</span>
<!-- end haloscan -->

<!-- START comment out for haloscan (part 3) 
     <a class='feed-link' expr:href='data:f.url' expr:type='data:f.mimeType' target='_blank'><data:f.name/> (<data:f.feedType/>)</a>
END comment out for haloscan (part 3) -->
<!-- start haloscan (part 3) -->
     <a class='feed-link' href='http://www.haloscan.com/members/rss.php?user=tatata7' target='_blank'>Comment Feed (RSS)</a>
<!-- end haloscan -->

<!-- START comment out for haloscan (part 2 - post) 
      <h4>
        <b:if cond='data:post.numComments == 1'>
          1 <data:commentLabel/>:
        <b:else/>
          <data:post.numComments/> <data:commentLabelPlural/>:
        </b:if>
      </h4>

      <b:if cond='data:post.commentPagingRequired'>
        <span class='paging-control-container'>
          <a expr:class='data:post.oldLinkClass' expr:href='data:post.oldestLinkUrl'><data:post.oldestLinkText/></a>
           
          <a expr:class='data:post.oldLinkClass' expr:href='data:post.olderLinkUrl'><data:post.olderLinkText/></a>
           
          <data:post.commentRangeText/>
           
          <a expr:class='data:post.newLinkClass' expr:href='data:post.newerLinkUrl'><data:post.newerLinkText/></a>
           
          <a expr:class='data:post.newLinkClass' expr:href='data:post.newestLinkUrl'><data:post.newestLinkText/></a>
        </span>
      </b:if>

      <dl id='comments-block'>
        <b:loop values='data:post.comments' var='comment'>
          <dt expr:class='"comment-author " + data:comment.authorClass' expr:id='data:comment.anchorName'>
            <a expr:name='data:comment.anchorName'/>
            <b:if cond='data:comment.authorUrl'>
              <a expr:href='data:comment.authorUrl' rel='nofollow'><data:comment.author/></a>
            <b:else/>
              <data:comment.author/>
            </b:if>
            <data:commentPostedByMsg/>
          </dt>
          <dd class='comment-body'>
            <b:if cond='data:comment.isDeleted'>
              <span class='deleted-comment'><data:comment.body/></span>
            <b:else/>
              <p><data:comment.body/></p>
            </b:if>
          </dd>
          <dd class='comment-footer'>
            <span class='comment-timestamp'>
              <a expr:href='data:comment.url' title='comment permalink'>
                <data:comment.timestamp/>
              </a>
              <b:include data='comment' name='commentDeleteIcon'/>
            </span>
          </dd>
        </b:loop>
      </dl>

      <b:if cond='data:post.commentPagingRequired'>
        <span class='paging-control-container'>
          <a expr:class='data:post.oldLinkClass' expr:href='data:post.oldestLinkUrl'>
            <data:post.oldestLinkText/>
          </a>
          <a expr:class='data:post.oldLinkClass' expr:href='data:post.olderLinkUrl'>
            <data:post.olderLinkText/>
          </a>
           
          <data:post.commentRangeText/>
           
          <a expr:class='data:post.newLinkClass' expr:href='data:post.newerLinkUrl'>
            <data:post.newerLinkText/>
          </a>
          <a expr:class='data:post.newLinkClass' expr:href='data:post.newestLinkUrl'>
            <data:post.newestLinkText/>
          </a>
        </span>
      </b:if>

      <p class='comment-footer'>

        <b:if cond='data:post.embedCommentForm'>
          <b:include data='post' name='comment-form'/>
        <b:else/>
          <b:if cond='data:post.allowComments'>
            <a expr:href='data:post.addCommentUrl' expr:onclick='data:post.addCommentOnclick'><data:postCommentMsg/></a>
          </b:if>
        </b:if>

      </p>
END comment out for haloscan (part 2 - post) -->
<!-- start haloscan (part 2 - post) -->
      <script src='http://www.haloscan.com/load/tatata7' type='text/javascript'> </script>
<span class='post-comment-link'>
<p><a class='comment-link' expr:href='"http://www.haloscan.com/comments/tatata7/" + data:post.id + "/"' expr:onclick='"HaloScan(" + "\""+ data:post.id + "\"" + ");return false;"'>
<script type='text/javascript'>postCount('<data:post.id/>');</script>
</a> | 
<a class='comment-link' expr:href='"http://www.haloscan.com/tb/tatata7/" + data:post.id + "/"' expr:onclick='"HaloScanTB(" + "\""+ data:post.id + "\"" + ");return false;"'>
<script type='text/javascript'>postCountTB('<data:post.id/>');</script>
</a></p>
<script expr:src='"http://www.haloscan.com/comments/tatata7/" + data:post.id + "/?m=1"' type='text/javascript'/>
<noscript><a expr:href='"http://www.haloscan.com/comments/tatata7/" + data:post.id + "/"'>Comments</a> | <a expr:href='"http://www.haloscan.com/tb/tatata7/" + data:post.id + "/"'>Trackback</a></noscript><br/>
</span>
<!-- end haloscan -->



失敗の原因がよく分からないんですけど、何となくHTMLのコメント(<!-- -->)が怪しい気がします。でも、それだとみんな失敗するはずですね。今までにやったテンプレートの編集が関係しているのかなぁ。

Blogger Syntax Highliter with Perl support

[ja] Blogger Syntax HighliterをPerlのコードに対応させました。Perlのコードの場合はpreタグに class="perl" を指定します。ウィジェットを追加するには下のボタンを押して下さい。

[en] I added Perl code support to Blogger Syntax Highliter. For Perl code, use class="perl" in pre tag. Click the button below to add this widget.

Widget 追加ボタンの作り方

クリボウの Blogger Tips「Blogger beta の Widget 追加ボタンの作り方」 を読んで、Perl対応したBlogger Syntax Highlighterウィジェットの追加ボタンを作ってみようかなと思い始めました。Perlのキーワードや関数の対応が十分にできているかどうか分かりませんけど...

2008/07/26

Perlのコードをハイライトしてみる

Blogger Syntax Highlighterウィジェットをちょっと弄ってみました。

まぁ、やったことはウィジェット (JavaScript) の最後の方にあるRubyを処理する部分をコピーして、次のページを参考に内容を書き換えてRubyを処理する部分の下に追加しただけなんですけど。




正規表現がよくわかんないので、たぶんPerlの変数を上手く引っ掛けられないと思いますが、今後直そうと思います。

テストで表示させるのに "Hello, world!" ではつまらないしPerlの変数も出てこないので、オープンストリートマップで国土数値情報インポート作業用の資料を作る際に、ファイルをソートするために使った短いスクリプトが残っていたので、それにしました。

preタグに class="perl" を指定して、果たして上手くいくのか...

#!/usr/bin/perl

#####
#
# データ調査用スクリプト UTF8ファイルのSORT
#
# KSJ2 Railway Data 2007 - EB02 (Railway Line)
# 国土数値情報(鉄道データ)平成19年 国土交通省 - EB02 (鉄道路線)
#
# Files
#   Input : N02-07_EB02-r1.osm
#   Output : N02-07_EB02-r1-sort.osm
#    
#####


use strict;
use warnings;
use encoding "utf8";
use Encode;
use open IO => "utf8";


sub main() {

 open(IN, "<N02-07_EB02-r1.osm");
 open(OUT, ">N02-07_EB02-r1-sort.osm");

 my $i = 0;
 my @file = <IN>;
 my @array = sort @file;

 foreach my $line(@array) {
   print OUT $line;
   $i++;
 }

 close IN;
 close OUT;

 printf "Output %d records\n", $i;   

}




# run this script.

main();





うーん、やっと出た。

予想通り最初は正規表現の所がおかしくて、JavaScriptの実行自体がエラーになり、全くのプレーンテキストしか表示されませんでした。その後、キーワードや関数の名前を登録している部分、それに対応するCSSなども修正。これからも少しづつ直す所が出てきそうな気がします。

でも、とりあえず今の時点で動いているものを貼っておきます。

dp.sh.Brushes.Perl=function()
{var keywords='break continue do elsif else for foreach goto if last next return sub undef unless '+'until while';var builtins='abs accept alarm atan2 bind binmode bless caller chdir chmod chomp chop chown '+'chr chroot close closedir connect continue cos crypt dbmclose dbmopen defined '+'delete die do dump each eof eval exec exists exit exp fcntl fileno flock fork '+'format formline getc getlogin getpeername getpgrp getppid getpriority getpwnam '+'getgrnam gethostbyname getnetbyname getprotobyname getpwuid getgrgid '+'getservbyname gethostbyaddr getnetbyaddr getprotobynumber getservbyport '+'getpwent getgrent gethostent getnetent getprotoent getservent setpwent '+'setgrent sethostent setnetent setprotoent setservent endpwent endgrent '+'endhostent endnetent endprotoent endservent getsockname getsockopt glob gmtime '+'goto grep hex import index int ioctl join keys kill last lc lcfirst length '+'link listen local localtime log lstat m map mkdir msgctl msgget msgsnd msgrcv '+'my next no oct open opendir ord our pack package pipe pop pos print printf '+'prototype push q qq qr qx qw quotemeta rand read readdir readline readlink '+'readpipe recv redo ref rename require reset return reverse rewinddir rindex '+'rmdir s scalar seek seekdir select semctl semget semop send setpgrp '+'setpriority setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep '+'socket socketpair sort splice split sprintf sqrt srand stat study substr '+'symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied '+'time times tr truncate uc ucfirst umask undef unlink unpack untie unshift use '+'utime values vec wait waitpid wantarray warn write y'
this.regexList=[{regex:dp.sh.RegexLib.SingleLinePerlComments,css:'comment'},{regex:dp.sh.RegexLib.DoubleQuotedString,css:'string'},{regex:dp.sh.RegexLib.SingleQuotedString,css:'string'},{regex:new RegExp(':[a-z][A-Za-z0-9_]*','g'),css:'symbol'},{regex:new RegExp('(\\$|@|%|\\*)\\w+','g'),css:'variable'},{regex:new RegExp(this.GetKeywords(keywords),'gm'),css:'keyword'},{regex:new RegExp(this.GetKeywords(builtins),'gm'),css:'builtin'}];this.CssClass='dp-pl';this.Style='.dp-pl .symbol { color: #a70; }'+'.dp-pl .variable { color: #a70; font-weight: bold; }'+'.dp-pl .builtin { color: #069; font-weight: bold; }';}
dp.sh.Brushes.Perl.prototype=new dp.sh.Highlighter();dp.sh.Brushes.Perl.Aliases=['perl'];


桁番号表示のオプションは TeraPad みたいなものを勝手に想像していたので、ちょっとガッカリ。コードを見るにはメニューにある + expand source のリンクをクリックして下さい。

私はこれをウィジェット (JavaScript) の最後の方にある ['ruby','rails','ror']; で終わっている行の次に追加しています。

元のsyntaxhighlighterのページには"Code License: GNU Lesser General Public License"と書いてあるので、この部分もGLGPLということかな?  よくわからんけど...

2008年7月28日 追記

Perl対応部分を組み込んだウィジェットの追加ボタンを作成してみました。

おかげで、[設定] → [フォーマット] → 改行の変換を「いいえ」にして、自分でbrタグを入力して改行させなければいけなくなりました。「はい」だとウィジェットの中に在る改行までbrタグに変換されてしまうので...
Atom