// ? Comment Linker, released under the GPL
// http://www.gnu.org/copyleft/gpl.html
//
// ==UserScript==
// @name           Hatena Comment Linker
// @description    Looks for text strings in comments that look like URLs, and converts them to clickable hyperlinks.
// @include        http://d.hatena.ne.jp/*
// @include        http://*.g.hatena.ne.jp/*
// @include        http://b.hatena.ne.jp/*
// @include        http://i.hatena.ne.jp/*
// ==/UserScript==
//
// 2005-08-23 (v0.1) Initial Version.

(function(){
  const comments = document.evaluate('(/descendant::DIV[@class="commentshort"]/P|/descendant::DIV[@class="bookmarklist"]/UL/LI|/descendant::TABLE[@class="paymentlist"]/TBODY/TR/TD|/descendant::UL[@class="commentlist"]/LI)', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  const outerRE = /\u300e[\W\w]*\u300f/g; // within brackets
  const innerRE = /(?:(?:(a|b|d|f|i|r|graph):)?(id):([-_a-zA-Z0-9]{3,15})(?::(\w+)(?::(\w+)(?::[\w:]+)?)?)?|(g):([-_a-zA-Z0-9]{3,24})(?::id:([-_a-zA-Z0-9]{3,15})(?::(\w+)(?::(\w+))?)?)?|(question):(\d+)(?::[\w:]+)?|(idea):(\d+)(?::[\w:]+)?|(map):x([\d.]+)y([\d.]+)(?::[\w:]+)?|(isbn|asin):([\dX-]+)(?::[\w:]+)?|(jan|ean):([\dX-]+)(?::[\w:]+)?|(?:https?|ftp):\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+|mailto:[-_.!~*\'a-zA-Z0-9\/?&=+$%#^`{|}]+@[-.a-zA-Z0-9]+)(?=[^>]*(?:<|$))/g;
  
  for (var i = 0; i < comments.snapshotLength; ++i) {
    with (comments.snapshotItem(i)) {
      innerHTML = innerHTML.replace(outerRE, function (s) {
        return s.replace(innerRE, function (s, idName, id, idID, idDate, idTime, group, groupName, groupID, groupDate, groupTime, question, questionID, idea, ideaID, map, mapX, mapY, asin, asinID, ean, eanID) {
          if (id) {
            return s.link((idName ? 'http://' + idName + '.hatena.ne.jp/' : '/') + idID + '/' + (!idDate ? '' : idName == 'f' && idDate.match(/\d+/) ? RegExp.lastMatch : idDate + (!idTime ? '' : '/' + idTime)));
          }
          
          if (group) {
            return s.link('http://' + groupName + '.g.hatena.ne.jp/' + (!groupID ? '' : groupID + '/' + (!groupDate ? '' : groupDate + (!groupTime ? '' : '/' + groupTime))));
          }
          
          if (question) {
            return s.link('http://www.hatena.ne.jp/' + questionID);
          }

          if (idea) {
            return s.link('http://i.hatena.ne.jp/idea/' + ideaID);
          }

          if (map) {
            return s.link('http://map.hatena.ne.jp/?x=' + mapX + '&amp;y=' + mapY + '&amp;z=4');
          }

          if (asin) {
            return s.link('http://d.hatena.ne.jp/asin/' + asinID);
          }
          
          if (ean) {
            return s.link('http://d.hatena.ne.jp/ean/' + eanID);
          }
          
          try {
            return decodeURIComponent(s).link(s);
          }
          catch (e) {
            return s.link(s);
          }
        });
      });
    }
  }
})()

