2010/07/30

macportのインストール

macのパッケージ管理はmacportが便利です。毎回ビルドするのでちょっと遅いですが。
インストール方法はオフィシャルサイトからイメージをダウンロード後、インストールします。その後、.bash_profileに次のパスを追記します。
export PATH=/opt/local/bin:/opt/local/sbin/:$PATH
export MANPATH=/opt/local/man:$MANPATH

環境はSnowLeopardです。
Leopardからアップデートした場合にmigrationが必要になる場合があるようです。
方法はオフィシャルサイトに書いてあります。
port installed > myports.txt
sudo port -f uninstall installed
sudo port clean --work --archive all
これで全て消したあと自動的に再インストールするスクリプトを実行。
curl -O http://svn.macports.org/repository/macports/contrib/restore_ports/restore_ports.tcl
chmod +x restore_ports.tcl
sudo ./restore_ports.tcl myports.txt
上がダメな場合はmyport.txtを見ながら手動で入れてくれとのこと。
sudo port install portname +variant1 +variant2 ...

公開鍵の作り方

sftpなどのための公開鍵の作り方についてまとめておきます。
$ whoami
(ユーザー名)
$ ssh-keygen -t rsa //カギを作成する
Generating public/private rsa key pair.
Enter file in which to save the key (/home/(ユーザー名)/.ssh/id_rsa):
Created directory '/home/(ユーザー名)/.ssh'.   
Enter passphrase (empty for no passphrase): //パスワードを入力
Enter same passphrase again: //もう一度パスワードを入力
Your identification has been saved in /home/(ユーザー名)/.ssh/id_rsa.
Your public key has been saved in /home/(ユーザー名)/.ssh/id_rsa.pub.
The key fingerprint is:
ff:8a:6b:d8:eb:ad:68:90:33:eb:2c:6c:d8:ea:98:41 (ユーザー名)@(PC名)
$ ls -la ~/.ssh //確認
合計 16
drwx------    2 xxx     xxx         4096 Feb  2 13:53 ./
drwx------   22 xxx     xxx         4096 Feb  2 13:53 ../
-rw-------    1 xxx     xxx          951 Feb  2 13:53 id_rsa     //秘密鍵
-rw-r--r--    1 xxx     xxx          236 Feb  2 13:53 id_rsa.pub //公開鍵
$ mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys //authorized_keysにリネーム

SnowLeopardにPerl環境構築

基本はモダンなPerlの開発環境の構築方法を参考にする。

Xcodeは普通に入れて下さい。
Perlbrewを入れる。
$ curl -LO http://xrl.us/perlbrew
$ chmod +x perlbrew
$ ./perlbrew install
.bachrc_profileにsource ~/perl5/perlbrew/etc/bashrc を追記。
.bachrc_profileファイルは無かったので新規に作る。
ターミナルを再起動してPerlを最新版にする。
% perlbrew install perl-5.12.1
% perlbrew switch perl-5.12.1
ちょっと時間がかかるので待つ。
cpanmを入れる。今回はGitで入れました。
$ git clone git://github.com/miyagawa/cpanminus.git
$ cd cpanminus
$ perl Makefile.PL
$ make install

local::lib をインストールする。
$ cpanm local::lib
ここまでがリンク先で書かれていたPerl開発環境。

cpam moduleをアップデート。
$ cpanm App::cpanoutdated
$ cpan-outdated | cpanm -L ~/perl5
Plaggerをインストール。
$ git clone git://github.com/miyagawa/plagger.git
$ cd plagger
$ cpanm -L ~/perl5 .

2010/07/20

memcachedの起動メモ

memcachedの起動メモ。メモリ1Gで接続許可はローカルホストの場合
memcached -u memcached -d -m 1024 -l 127.0.0.1

2010/07/19

ブラウザ三国志で書簡を保存するグリモンを修正

http://www.ai-mai.net/archives/2010/01/post-2.phpにて公開されていたGreasemonkeyスクリプトを取りあえず動くように修正。今回はChrome対応してません。(というか31行目jsonObj.toSource()が上手くいかなかった)自己責任でお願いします。

ファイルはこちら
// ==UserScript==
// @name           bura3_MailBox
// @description    書簡を保存する
// @include        http://*.3gokushi.jp/message/inbox.php
// @include        http://*.3gokushi.jp/message/inbox.php#*
// @include        http://*.3gokushi.jp/message/inbox.php?p=1*
// ==/UserScript==

var oldData = getData();
//初回(自ページから)のnext link
var nextUri = "";
//カウンタ
var offset = 0;
//本文内の情報を格納
var mailBoxSet = new Array();
//本文へのURIを格納
var mailUri =  new Array();

var LOCAL_STORAGE = "bro3_mailbox";

//XPath
function xpath(query,targetDoc) {return document.evaluate(query, targetDoc, null,XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);}

//GM永続データの取得
function getData(){
  return eval(GM_getValue(location.host + "MailBox"));
}

//GM永続データの保存
function setData(jsonObj){
  GM_setValue(location.host + "MailBox", jsonObj.toSource());
}

//渡されたHTMLデータから書簡本文へのリンクだけを抜き出す
function mailUriSet(htmlData){
  var htmlSnap = xpath("//table[@class='commonTables']/tbody/tr/td[2]/a", htmlData);
  for (i=0; i < htmlSnap.snapshotLength; i++){
    mailUri[offset] = htmlSnap.snapshotItem(i).href;
    offset++;
  }
  if (htmlData == document){
    //次に画面下部のnext linkから抜き出し
    nextUriFetch();
  }
}

//リンクを一気に取得
function nextUriFetch(){
  var nextXhr = new XMLHttpRequest();
  //nextXhr.open("GET",nextUri);
  //nextXhr.send(null);

 // nextXhr.onreadystatechange = function(){
  //  if(nextXhr.readyState ==4){
  //    if(nextXhr.status == 200){
        //パーサーチックに
        var newDiv = document.createElement("div");
        newDiv.innerHTML = nextXhr.responseText;
        //パースしたのをmailUriSetに投げる。
        mailUriSet(newDiv);
        //スマートじゃないけど面倒臭いからこれで
        try{
            nextUri = newDiv.getElementsByClassName("last")[1].childNodes[0].href
        }
        catch(e){
          offset = 0;
          //アーカイブと同じIDのは削除する。
          var tmpIdx = 0;
          var changeFlag = false;
          if(oldData){
            for(var i=0; i < mailUri.length;){
              for(var j=0; j<oldData.length; j++){
                if(oldData[j][0] == mailUri[i].match("id=[0-9]+")[0].split("=")[1]){
                  changeFlag = true;
                  break;
                }
              }
              if(changeFlag){
                mailUri.splice(i,1);
                changeFlag = false;
              }
              else{
                i++;
              }
            }
          }
          //nextをすべて抜き出しおわったら本文内の処理をやっていく。
          xhr();
          return;
        }
        nextUriFetch();
      //}
    //}
  //}
}

//XHR用の再帰関数
function xhr(){
  //オブジェクトが無かったらおしまい。
  if(!mailUri[offset]){
    //make save data
    makeSaveData();
    nextUri = document.getElementsByClassName("last")[1].childNodes[0].href;
    alert("保存処理が終わりました。");
    return 0;
  }
  targetUri = mailUri[offset];
  //XHR
  var xmlhttp = new XMLHttpRequest();
  xmlhttp.open("GET",targetUri);
  xmlhttp.send(null);
  //ステータスチェンジで発生するイベント
  xmlhttp.onreadystatechange = function(){
    //ifネストしてるのはキャッシュ判定とかのためだけどたぶん使わない
    if(xmlhttp.readyState ==4){
      if(xmlhttp.status == 200){
        //パーサー
        var responseXML = document.createElement("div");
        responseXML.innerHTML = xmlhttp.responseText;
        //書簡の部分だけを取得
        var message = responseXML.getElementsByClassName("ttl w80");
        mailBoxSet[offset] = new Array();
        //uriのIDをメッセージIDにしてunique管理
        mailBoxSet[offset][0] = targetUri.match("id=[0-9]+")[0].split("=")[1];
        for(var i=0; i<message .length; i++){
            mailBoxSet[offset][i+1]  = message [i].parentNode.getElementsByTagName("td")[0].innerHTML
        }
        offset++;
        xhr();
      }
    }
  }
}

function makeSaveData(){
  var saveData = getData();
  if(saveData){
    var numOfOld = saveData.length;
  }
  else{
    var numOfOld = 0;
    saveData = new Array();
  }
  for(i=0; i < mailBoxSet.length; i++){
    saveData[numOfOld + i] = mailBoxSet[i];
  }
  setData(saveData);
}

function startSave(){
  //まずは自ページ(p=1)から書簡本文リンクの抜き出し
  mailUriSet(document);
}

//このへんから実行
initGMWrapper();
var mailMenu = document.getElementById("statMenu");

//保存用
var saveButton = document.createElement("span");
saveButton.innerHTML = "<input id='saveMail' type='button' value='書簡保存' />";
saveButton.id = "saveButton";
saveButton.style.padding = "0 10px 0 0";
mailMenu.appendChild(saveButton);

//表示
var archiveButton = document.createElement("span");
archiveButton.innerHTML = "<input id='archiveButton' type='button' value='アーカイブ' />";
archiveButton.id = "archivebutton";
archiveButton.style.padding = "0 10px 0 0";
mailMenu.appendChild(archiveButton);

//削除
var delButton = document.createElement("span");
delButton.innerHTML = "<input id='delButton' type='button' value='削除' />";
delButton.id = "delButton";
delButton.style.padding = "0 10px 0 0";
mailMenu.appendChild(delButton);

document.getElementById("saveButton").addEventListener("click",
    function() {
        oldData = getData();
        nextUri = document.getElementsByClassName("last")[1].childNodes[0].href;
        mailBoxSet = []
        //本文へのURIを格納
        mailUri =  []
        offset = 0;
        startSave();
    },true);

document.getElementById("archiveButton").addEventListener("click",
  function() {
    var archiveInner = "";
    var archiveData = getData();
    if(archiveData){
      for(var i=0; i < archiveData.length; i++){
        archiveInner += 
          "<tr><td><input name='chk[]' value='" + archiveData[i][0] + "' type='checkbox'>" +
          "</td><td><a href='javascript:void(0)' name='mboxTitle' id='" + archiveData[i][0] + "'>" + archiveData[i][4] + "</a>" +
          "</td><td>" + archiveData[i][1] +
          "</td><td class='fs77'>" + archiveData[i][3] +
          "</td></tr>";
      }
      var tableHead = "<tbody><tr><th class='ttl w30'>選択</th><th class='ttl w300'>件名</th><th class='ttl'>送信者</th><th class='ttl w120'>送信時間</th></tr><tr></tr>";
      var tableFoot = "</tbody>";
      document.getElementsByClassName("commonTables")[0].innerHTML = tableHead + archiveInner + tableFoot;
      //本文表示イベントリスナーの設定
      var mboxTitle = document.getElementsByName("mboxTitle");
      for(var i=0; i<mboxTitle.length; i++){
        (function(i){
          mboxTitle[i].addEventListener("click",function(){
              for(var j=0; j<archiveData.length; j++){
                if(archiveData[j][0] == mboxTitle[i].id){
                  var mesinnerHTML = "<tbody><tr><th class='ttl w80'>送信者</th><td>" + archiveData[j][1] +
                                     "</td></tr><tr><th class='ttl w80'>宛先</th><td>" + archiveData[j][2] +
                                     "</td></tr><tr><th class='ttl w80'>日時</th><td>" + archiveData[j][3] +
                                     "</td></tr><tr><th class='ttl w80'>件名</th><td>" + archiveData[j][4] +
                                     "</tr><tr><th class='ttl w80'>本文</th><td>" +archiveData[j][5] + "</td></tr></tbody>";
                  document.getElementsByClassName("commonTables")[0].innerHTML = mesinnerHTML;
                  return;
                }
              }
          },false);
        })(i);
      }
    }
    else{
      alert("アーカイブデータはありません。")
    }
  },true
);

document.getElementById("delButton").addEventListener("click",
   function() {
      if(confirm('全てのデータを削除します。')){
        GM_setValue(location.host + "MailBox", "")
        alert("削除しました。")
      }
    },true);

//Google Chrome用GM_*系ラッパー関数
function initGMWrapper() {
  // @copyright   2009, James Campos
 // @license  cc-by-3.0; http://creativecommons.org/licenses/by/3.0/
 if ((typeof GM_getValue == 'undefined') || (GM_getValue('a', 'b') == undefined)) {
  GM_addStyle = function(css) {
   var style = document.createElement('style');
   style.textContent = css;
   document.getElementsByTagName('head')[0].appendChild(style);
  }

  GM_deleteValue = function(name) {
   localStorage.removeItem(LOCAL_STORAGE + "." + name);
  }

  GM_getValue = function(name, defaultValue) {
   var value = localStorage.getItem(LOCAL_STORAGE + "." + name);
   if (!value)
    return defaultValue;
   var type = value[0];
   value = value.substring(1);
   switch (type) {
    case 'b':
     return value == 'true';
    case 'n':
     return Number(value);
    default:
     return value;
   }
  }

  GM_log = function(message) {
   console.log(message);
  }

  GM_registerMenuCommand = function(name, funk) {
  //todo
  }

  GM_setValue = function(name, value) {
   value = (typeof value)[0] + value;
   localStorage.setItem(LOCAL_STORAGE + "." + name, value);
  }
  
  //by froo
  GM_listValues = function() {
   var res = new Array();
   for (var i = 0; i < localStorage.length; i++) {
    var key = localStorage.key(i);
    if (key.indexOf(LOCAL_STORAGE + ".", 0) == 0) {
     res.push(key.replace(/^.*?\./, ""));
    }
   }
   return res;
  }
 }
}

2010/07/16

ブラウザ三国志で武将を一覧表示するGreaseMonkeyスクリプトを修正

こちらにて公開されてたブラウザ三国志で武将を一覧表示するgreasemonkeyスクリプトが動かなくなっていたのでやっつけで修正しました。レベル取得の部分は面倒なので飛ばしました。Chromeでも動きます。

ファイルはこちら
// ==UserScript==
// @name           bura3deckext
// @version        0.0
// @description    
// @include        http://*.3gokushi.jp/card/deck.php*
// ==/UserScript


function getListElement()
{
 var list = document.getElementById("sol_list");
 if (!list) {
  list = document.createElement('table');
  list.id = "sol_list";

  var attrname = ["","コスト","ID","名前","HP","攻撃","知力","歩防",
   "槍防","弓防","騎防","速度","操作","cid"];
  var attr = ["","","cost","cardno","name1","status_hp","status_att",
   "status_int","status_wdef","status_sdef","status_bdef","status_rdef","status_speed","",""];
  var sortable = [0,1,1,0,0,1,1,1,1,1,1,1,0,0];

  row = document.createElement('tr');
  row.id = "sol_list_header"
  for (j=0;j<attrname.length;j++) {
   e = document.createElement('th');
   e.id="sol_list_" + attr[j];
   e.innerHTML = attrname[j];
   row.appendChild(e);
  }
  list.appendChild(row);


  var file = document.getElementById("card_uraomote");
  file.insertBefore(list,file.firstChild);

  sortableTable(list);
  for (j=0;j<attrname.length;j++) {
   if (sortable[j]==1) list.setSortable(j);
  }
 }
 return list;
}

function sortableTable(tbl)
{
 tbl.setSortable = function (col,mode)
 {
  var e = tbl.childNodes[0].childNodes[col];
  e.style.cursor = "pointer";
  e.orgClassName = e.className;
  e.addEventListener('click',function(s){return function(){tbl.sortTable(s);};}(col),false);
  e.addEventListener('mouseover',function(){this.className+=" hover";},false);
  e.addEventListener('mouseout' ,function(){this.className=this.orgClassName;},false);
 };

 tbl.sortTable = function sortTable(col)
 {
  rows= new Array();
  for (i=1;i<tbl.childNodes.length;i++) {rows[i-1]=tbl.childNodes[i];}
  rows.sort(function(a,b){
   ea=a.childNodes[col];
   eb=b.childNodes[col];
   if (!ea) return -1;
   if (!eb) return 1;
   return parseFloat(eb.firstChild.nodeValue)-parseFloat(ea.firstChild.nodeValue);
  });
  for (i=0;i<rows.length;i++) {tbl.appendChild(rows[i]);}
 }

 return tbl;
}


function addcards(d){
 var list = getListElement();
 var deckFile = d.getElementsByClassName("file")[0];
 var currentDeckFile = document.getElementById("deck_file");
 var cards = deckFile.getElementsByClassName("cardStatusDetail");
 if (!cards.length) {
  cards = deckFile.getElementsByClassName("cardColmn");
 }

 var attr = ["cost","cardno","name1","status_hp","status_att",
  "status_int","status_wdef","status_sdef","status_bdef","status_rdef","status_speed"];

 for (i=0;i<cards.length;i++) {
   row = document.createElement("tr");
   row.className="infile";

   t = cards[i].getElementsByClassName("soltype");
   e = document.createElement('td');
   e.innerHTML = t[0].innerHTML;
   row.appendChild(e);

   for (j=0;j<attr.length;j++) {
    t = cards[i].getElementsByClassName(attr[j]);
    if(!t) continue;
    e = document.createElement("td");
    e.className="cell_" + attr[j];
    e.innerHTML = t[0].innerHTML;
    row.appendChild(e);
   }

   t = cards[i].getElementsByClassName("cardWrapper2col");
   var cid = undefined;
   if (t.length) {
    cid = t[0].parentNode.id.split("_")[1];
   } else {
    t = cards[i].getElementsByClassName("cardDelete")[0].firstChild;
    if (t.getAttribute)
    if (re=t.getAttribute('onclick').match(/operationExecution\('[^']*', (\d+), '[^']*', \d+\)/)) {
     cid = re[1];
    }
   }

   e = document.createElement("td");

   t = cards[i].getElementsByClassName("aboutdeck");
   if(t.length && t[0].getAttribute('onclick')) {
    var link = document.createElement("a");
    link.href="javascript:((function(){"+t[0].getAttribute('onclick')+"})(),void(0));";
    link.appendChild(document.createTextNode("[セット]"));

    t=cards[i].getElementsByTagName("select");
    if (t.length) {
     t=t[0];
     e.appendChild(t);
     var v = document.createElement("input");
     v.name = t.name;
     v.value = t.value;
     currentDeckFile.appendChild(v);
     t.addEventListener('change',(function (a,b){return function(){a.value=b.value};})(v,t),false);
    }
    e.appendChild(link);
   } else {
    e.appendChild(document.createTextNode(" セット不可 "));
   }
   row.appendChild(e);

   e = document.createElement("td");
   if (cid) {
    e.innerHTML = "<a href='status_info.php?cid=" + cid + "'>"+cid+"</a>";
   } else {
    e.innerHTML = "-";
   }
   row.appendChild(e);

   list.appendChild(row);
 }
}

function addcards_deck(d){
 var list = getListElement();
 var cardListDeck = document.getElementById("cardListDeck");
 var cards = cardListDeck.getElementsByClassName("cardColmn");

 var attr = ["cost","cardno","name1","status_hp","status_att",
  "status_int","status_wdef","status_sdef","status_bdef","status_rdef","status_speed"];

 for (i=0;i<cards.length;i++) {
  row = document.createElement('tr');
  row.className="indeck";

  t = cards[i].getElementsByClassName("soltype");
  e = document.createElement('td');
  e.innerHTML = t[0].innerHTML;
  row.appendChild(e);

  for (j=0;j<attr.length;j++) {
   t = cards[i].getElementsByClassName(attr[j]);
   if(!t) continue;
   e = document.createElement('td');
   e.className="cell_" + attr[j];
   e.innerHTML = t[0].innerHTML;
   row.appendChild(e);
  }

  t = cards[i].getElementsByTagName("dd")[2];
  e = document.createElement('td');
  e.innerHTML = t.innerHTML;

  t = cards[i].getElementsByClassName("aboutdeck");
  if(t.length && t[0].getAttribute('onclick')) {
   var link = document.createElement("a");
   link.href="javascript:((function(){"+t[0].getAttribute('onclick')+"})(),void(0));";
   link.appendChild(document.createTextNode("[戻す]"));
   e.appendChild(link);
  }


  row.appendChild(e);
  e = document.createElement("td");
  e.innerHTML = "-";
  row.appendChild(e);

  list.appendChild(row);
 }
}

function createlist(){
 addcards_deck(document);
 addcards(document);
 //return;

 t = document.getElementsByClassName("pager")[0].getElementsByTagName("a");
 for(i=0;i<t.length;i++) {
  if (!t[i].innerHTML.match(/\d/)) continue;

  httpRequest = new XMLHttpRequest();
  httpRequest.open('GET', t[i].href, true);

  httpRequest.onreadystatechange = function (){
   var req = arguments[0];
   return function(){
       if(req.readyState == 4 && req.status == 200) {
      var d = document.createElement('html');
      d.innerHTML=req.responseText;
      addcards(d);
    }
   };
  }(httpRequest);
  httpRequest.send(null);

 }
}


( function(){
 
 GM_addStyle(""
  + "#sol_list{border-style:solid;border-spacing: 2px;border-collapse: separate;width:100%;}"
  + "#sol_list tr{height:22px;}"
  + "#sol_list tr td{height:1.2em;padding-left:4px;}"
  + "#sol_list tr th{background-color:#ccc;text-align:center;}"
  + "#sol_list tr th.hover{background-color:#ddd;}"
  + " tr.indeck{background-color:#ddf}"
  + ".cell_name2{font-size:0.5em;color:#888;}"
 );

  var link = document.createElement("a");
  link.addEventListener('click',createlist,false);
  link.href="javascript:void(0)";
  link.innerHTML = "武将一覧"
  var menu = document.getElementById("statMenu");
  menu.appendChild(document.createTextNode(" | "));
  menu.appendChild(link);
     
}) (); 




いつものように自己責任で。

2010/07/10

shellスクリプトパラメーターの渡し方

Shellスクリプトのパラメーターは$0,$1,$2…で呼び出せます。$0はファイル名、$1からパラメーターになります。
#!/bin/sh
echo $1
という形でtest.shファイルを作成した場合は次の通りです。
$ sh test.sh hello
hello

2010/07/08

GAEでjrubyをためしてみる

まずここからSDKのインストール。ファイルを解凍すると一式が入ってます。

gemにてgoogle-appengneをインストール
sudo gem install google-appengine
サンプルアプリを作って動かす
appcfg.rb generate_app hello
dev_appserver.rb hello
helloディレクトリ以下にアプリが作られます。
config.ruファイルにアプリケーションID等が記載されています。

ローカルサーバーで動かします。
dev_appserver.rb hello
本番環境(GAE)にアップロード
appcfg.rb update hello
メールアドレス、パスワードを聞かれるので入力。
完了。

2010/07/05

ブラウザ三国志GreasemonkeyスクリプトMap-StarをChrome対応させてみた(2)

以前に書いたスクリプトですが、7月5日のアップデートにて動かなくなりました。またろむのシ的メモ+αさんが即対応してくださったみたいですが、Chrome版が動かなかったのでGreasemonkey版をベースに修正してみました。

ファイルをダウンロード
// ==UserScript==
// @name           3gokushi-MapStar-chrome
// @namespace      3gokushi
// @description    ブラウザ三国志のマップに★の数を表示します。クローム対応版
// @include        http://*.3gokushi.jp/map.php*
// ==/UserScript==

var LOCAL_STORAGE = "bro3_mapstar";

//main
(function(){
//window.addEventListener("load",function() {
initGMWrapper();

    if (typeof GM_addStyle == "undefined") {
        GM_addStyle = function(css) {
            var style = document.createElement('style');
            style.textContent = css;
            document.getElementsByTagName('head')[0].appendChild(style);
        };
    }


    GM_VAL_PREFIX = "GMMS_";

    /**
     * 設定データ初期化
     */
    var dataTable = {
        w : new Array("#FFFFFF", "#000000", GM_getValue(GM_VAL_PREFIX + "w", true)), // white
        r : new Array("#FF0000", "#FFFFFF", GM_getValue(GM_VAL_PREFIX + "r", true)), // red
        g : new Array("#00FF00", "#000000", GM_getValue(GM_VAL_PREFIX + "g", true)), // green
        b : new Array("#0000FF", "#FFFFFF", GM_getValue(GM_VAL_PREFIX + "b", true)), // blue
        y : new Array("#FFFF00", "#000000", GM_getValue(GM_VAL_PREFIX + "y", true)), // yellow
        p : new Array("#FF00FF", "#FFFFFF", GM_getValue(GM_VAL_PREFIX + "p", true)), // pink
        bk : new Array("#000000", "#FFFFFF", GM_getValue(GM_VAL_PREFIX + "bk", true)), // black
        bg : new Array("#0066FF", "#FFFFFF", GM_getValue(GM_VAL_PREFIX + "bg", true)), // sky blue
        o : new Array("#FFA500", "#000000", GM_getValue(GM_VAL_PREFIX + "o", true)) // orange
    };

    /**
     * styleの追加
     */
    GM_addStyle([
                 ".mapStar_outer{ width:10px;height:10px;margin:2px 4px 2px 0px;float:left;border:1px solid #000000;cursor:pointer; }",
                 ".mapStar_on{ filter:alpha(opacity=100);opacity:1; }",
                 ".mapStar_off{ filter:alpha(opacity=30);opacity:0.3;border:1px solid #999999; }",
                 ".mapStar_box{ filter:alpha(opacity=60);opacity:0.6; position: absolute; width: 8px; height: 8px; padding: 0px 0px 2px 3px; font-size: 8px;}",
               ].join("\n"));


    /**
     * 設定on/off処理関数
     */
    function onSettingClick() {
        var key = this.getAttribute("type");
        var gmv = GM_getValue(GM_VAL_PREFIX + key, true);
        GM_setValue(GM_VAL_PREFIX + key, !gmv);

        var clsName;
        var displayVal;
        if (gmv) {
            clsName = "mapStar_off";
            visibleVal = "hidden";
        } else {
            clsName = "mapStar_on";
            visibleVal = "visible";
        }

        var XPath = '//div[@class="mapStar_margin mapStar_box mapStar_' + key + '"]';
        var list = document.evaluate(XPath, document, null,
                XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

        for ( var i = 0; i < list.snapshotLength; i++) {
            list.snapshotItem(i).style.visibility = visibleVal;
        }

        XPath = '//div[@type="' + key + '"]';
        document.evaluate(XPath, document, null,
                XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.className = "mapStar_outer " + clsName;

    }

    /**
     * 設定ボックスの挿入
     */
    var insset = document.getElementById('mapboxInner');

    if (insset != null) {
        var set = document.createElement('div');
            set.style.backgroundColor = "#FFFFFF";
            set.setAttribute("id","mapStarBox");
            insset.appendChild(set);
        var cssText = "";
        for ( var key in dataTable) {
            var onoff = dataTable[key][2] ? "mapStar_on" : "mapStar_off";
            var setItem = document.createElement('div');
                setItem.className = "mapStar_outer " + onoff;
                setItem.style.backgroundColor = dataTable[key][0];

                set.appendChild(setItem);
                setItem.setAttribute("type", key);
                setItem.addEventListener("click", onSettingClick,false);
            cssText += ".mapStar_"+key+"{background-color:"+dataTable[key][0]+"; color:"+dataTable[key][1]+"} ";
        }
    }
    
    GM_addStyle(cssText);

    /**
     * MAPサイズ取得
     */
    var mapSize = document.getElementById('rollover').style.zIndex - 1;

    /**
     * 地図データの取得
     */
    var mapMap = new Array(mapSize + 1);
    var mapAreaDoc = document.getElementById('mapsAll');
    var imgRegCmp = new RegExp(/img\/panel\/[^_]*_([^_]*)_/);

    var imgMap = mapAreaDoc.getElementsByTagName('img');
    for ( var i = 0; i < imgMap.length; i++) {
        var clstxt = imgMap[i].className;
        if ((clstxt != null) && (clstxt.search(/mapAll(\d+)/) != -1)) {
            var mapIndex = RegExp.$1 - 0;
            var imgSrc = imgMap[i].src;
            if (imgRegCmp.exec(imgSrc)) {
                var imgRegCmp = new RegExp(/img\/panel\/[^_]*_([^_]*)_/);
                mapMap[mapIndex] = RegExp.$1;
            } else if (0 <= imgSrc.indexOf("blanc")) {
                mapMap[mapIndex] = "wall";
            }
        }
    }

    /**
     * 地図へ埋め込み
     *
     */
    var areas = mapAreaDoc.getElementsByTagName('area');

    // mapSizeからzIndexの値とmarginSizeを決定する
    var marginSize = "32px 0px 0px 23px";
    var zIndex = mapSize + 2;
    if (200 < zIndex && zIndex < 400) {
        marginSize = "25px 0px 0px 17px";
    } else if (400 <= zIndex) {
        marginSize = "16px 0px 0px 12px";
    }
    
    cssText = ".mapStar_margin{ margin:"+marginSize+"; z-index:"+zIndex+"; }";
    GM_addStyle(cssText);

    var regCmp = new RegExp(
            /(\'[^\']*\'[^\']*){5}\'(\u2605+)\'.*overOperation\(\'.*\'.*\'(.*)\'.*\'(.*)\'/);
    var j = 0;

    var alpha = 6;
    for ( var i = 1; i < mapMap.length; i++) {
        if (mapMap[i] != "undefined" && mapMap[i] == "wall") {
            continue;
        }

        if (areas[j] == "undefined") {
            break;
        }
        var mo = areas[j++].getAttribute('onmouseover');
        if (mo.search(/\u2605/) < 0) {
            continue;
        }

        if (regCmp.test(mo)) {
            var dataKey = (typeof mapMap[i] == "undefined") ? "w" : mapMap[i];

            var div = document.createElement('div');
            if (!dataTable[dataKey][2]) {
                div.style.visibility = "hidden";
            }

            div.className = "mapStar_margin mapStar_box mapStar_" + dataKey;
            div.setAttribute("id","mapStar_"+i);
            div.style.left = RegExp.$3;
            div.style.top = RegExp.$4;
            div.innerHTML = RegExp.$2.length;

            if (RegExp.$2.length >= 5) {
                div.style.border = "1px solid";
            }
            if (RegExp.$2.length >= 3) {
                div.style.fontWeight = "bold";
            }

            mapAreaDoc.appendChild(div);
        }
    }

//},false);
})();

//Google Chrome用GM_*系ラッパー関数
function initGMWrapper() {
  // @copyright   2009, James Campos
 // @license  cc-by-3.0; http://creativecommons.org/licenses/by/3.0/
 if ((typeof GM_getValue == 'undefined') || (GM_getValue('a', 'b') == undefined)) {
  GM_addStyle = function(css) {
   var style = document.createElement('style');
   style.textContent = css;
   document.getElementsByTagName('head')[0].appendChild(style);
  }

  GM_deleteValue = function(name) {
   localStorage.removeItem(LOCAL_STORAGE + "." + name);
  }

  GM_getValue = function(name, defaultValue) {
   var value = localStorage.getItem(LOCAL_STORAGE + "." + name);
   if (!value)
    return defaultValue;
   var type = value[0];
   value = value.substring(1);
   switch (type) {
    case 'b':
     return value == 'true';
    case 'n':
     return Number(value);
    default:
     return value;
   }
  }

  GM_log = function(message) {
   console.log(message);
  }

  GM_registerMenuCommand = function(name, funk) {
  //todo
  }

  GM_setValue = function(name, value) {
   value = (typeof value)[0] + value;
   localStorage.setItem(LOCAL_STORAGE + "." + name, value);
  }
  
  //by froo
  GM_listValues = function() {
   var res = new Array();
   for (var i = 0; i < localStorage.length; i++) {
    var key = localStorage.key(i);
    if (key.indexOf(LOCAL_STORAGE + ".", 0) == 0) {
     res.push(key.replace(/^.*?\./, ""));
    }
   }
   return res;
  }
 }
}

rubyでepubファイルを作ることができるRepubを試してみる

rubyでepubファイルを作ることができるrepubを試してみた。

まずインストール
sudo gem install repub
libxm2が古いと言われたので更新してnokogiriを再インストール
sudo port install libxml2
sudo gem install nokogiri 
** ERROR: : helper not found.のエラー
wgetが入ってなかったのでインストール
sudo port install wget
コマンド実行でOK(エンコードをUTF-8を設定)
repub -e 'UTF-8' サイトURL
ただ色々とサポートしてない部分があるようでかなりのサイトで利用できないみたい。Tumblrはepub化できました。
補足 epubリーダーとしてはFirefox Add-onのEPUBReaderがいい感じ。