Yet Another Hatena Referer Viewer
1/23ã®æ¥è¨ã§å ¬éããHatena Referer Viewerãããã«ãã¼ã¸ã§ã³ã¢ãããããå¤æ´ç¹ã¯ä»¥ä¸ã®éãï¼
- JAN/EANãã¼ã¸ã«å¯¾å¿ãã
- getNodesFromXPath()ã¨$X()ãapplication/xhtml+xmlãªãã¼ã¸ã§åããªãã¨ãããã°ï¼ãã®ã¹ã¯ãªããã§ã¯å ã å®å®³ãªãï¼ããã£ãã®ã§ä¿®æ£ãã
- å ¨ä½çã«ããã°ã©ã ã®æ§é ããªãã¡ã¯ã¿ãªã³ã°ãã
- å ã®ã¹ã¯ãªããã¨ååãåãã ã¨ç´ããããã®ã§å¤æ´ããï¼é ã«Yet Anotherãä»ããã ãã®å®ç´ãªãã¼ãã³ã°ã ãã©ï¼
YetAnotherHatenaRefererViewer.user.js
// ==UserScript== // @name Yet Another Hatena Referer Viewer // @namespace http://d.hatena.ne.jp/nozom/ // @author nozom <[email protected]> // @description Rearranges Hatena Diary's referer view. // @include http://d.hatena.ne.jp/* // @include http://*.g.hatena.ne.jp/* // ==/UserScript== // This script was originally published by motormean <[email protected]> at the following pages: // - http://tokyoenvious.xrea.jp/b/software/firefox/hatena_ref_view.html // - http://tokyoenvious.xrea.jp/b/software/firefox/hatena_ref_view_2.html // ver 2007-01-29 (function() { /*===== è¨å® =====*/ // ã¯ã¦ãªãã¼ã¯ã¼ã // var patKeywords = { '^http://(d2?|diary).hatena.ne.jp/keyword(mobile|diary|stats)?/([^\\?]+).*': '$3', '^http://(\\w+).g.hatena.ne.jp/keyword(mobile|diary)?/([^\\?]+).*': '[group:$1] $3', '^http://b.hatena.ne.jp/keyword/(.+)': '?B $1', '^http://r.hatena.ne.jp/keyword/([^/]+)$': '?R $1', }; // ã¯ã¦ãªãã¤ã¢ãªã¼ã»ã°ã«ã¼ã // var patDiaries = { '^http://(d|diary).hatena.ne.jp/([\\w-]+)/.*': 'id:$2', '^http://(\\w+).g.hatena.ne.jp/([\\w-]+)/.*': 'g:$1:id:$2', '^http://(\\w+).g.hatena.ne.jp/.*': 'g:$1', '^http://(d|diary).hatena.ne.jp/http\\?(.*)': '?D url(http:$2)', }; // ã¢ã³ãã // var patAntennae = { '^http://(a|antenna).hatena.ne.jp/([\\w-]+)/.*': '?A(id:$2)', '^http://(a|antenna).hatena.ne.jp/([^/]*)': '?A $2', '^http://i-know.jp/([\\w-]+).*': '?i-know($2)', }; // ããã¯ãã¼ã¯ // var patBookmarks = { '^http://b.hatena.ne.jp/t/([\\w-]+).*': '?B tag:$1', '^http://b.hatena.ne.jp/t\\?.*tag=([^&]*).*': '?B tag:$1', '^http://b.hatena.ne.jp/entry/(.+)': '?B ($1)', '^http://b.hatena.ne.jp/([\\w-]+)/$': '?B(id:$1)', '^http://b.hatena.ne.jp/([\\w-]+)(/.+)': '?B(id:$1) $2', '^http://b.hatena.ne.jp/(hotentry|entrylist.*)': '?B $1', '^http://clip.livedoor.com/clips/([^/]*)(.*)': 'livedoor clip($1) $2', '^http://del.icio.us/([^/?]*)(/.+)': 'del.icio.us($1) $2', '^http://del.icio.us/([^/?]*)?.*': 'del.icio.us($1)', }; // RSSãªã¼ãã¼ // var patRSS = { '^http://r.hatena.ne.jp/([\\w-]+)/$': '?R(id:$1)', '^http://r.hatena.ne.jp/([\\w-]+)/(.+?)/': '?R(id:$1) /$2/', '^http://r.hatena.ne.jp/([\\w-]+)/(.+?)/(http.+)': '?R(id:$1) /$2/ ($3)', '^http://r.hatena.ne.jp/([\\w-]+)/(http.+)': '?R(id:$1) ($3)', '^http://keyword.livedoor.com/w/(.*)': 'LDR(keyword:$1)', }; // ã¯ã¦ãªã¢ã¤ã㢠// var patIdeas = { '^http://i.hatena.ne.jp/idea/(\\d+)': '?I:$1', }; // ãã®ä»ã¯ã¦ãªå // var patHatena = { '^http://(d|diary)?.hatena.ne.jp/?([\\w-]*)': '?D $2', '^http://(\\w+).g.hatena.ne.jp/?([\\w-]*)': '?G($1) $2', '^http://g.hatena.ne.jp/?([\\w-]*)': '?G $1', '^http://f.hatena.ne.jp/?(\\w*)': '?F $1', '^http://www.hatena.ne.jp/(\\d+)/': 'question:$1', }; // æ¤ç´¢ã¨ã³ã¸ã³ // /* tDiary-users Project Wikiå * http://tdiary-users.sourceforge.jp/cgi-bin/wiki.cgi?referer_table * ããä¸é¨ã³ãã¼ããã¦ãããã¾ããã * ã©ã¤ã»ã³ã¹: Creative Commons License * http://creativecommons.org/licenses/by-nc/1.0/ */ var patSearches = { '^http://search.hatena.ne.jp/(web)?search\\?word=([^&]*)(&.*)?': '?Search($2)', '^http://www.google.([^/]+)/.*?(\\Wq|as_q)=([^&]*).*': 'Google($3)', '^http://www.google.([^/]+)/search.*?(\\Wq|as_q)=cache:[^:]*:([^\\s\\+]+)(\\s|\\+)([^&]*).*': 'Google($5) [Cache:$3]', '^http://blogsearch.google.com/blogsearch.*?\\Wq=([^&]*).*': 'Google($1)', // '^http://images.google.([^/]+)/.*?imgurl=([^&]*).*': 'Google image($2)', // '^http://\\w+.google.([^/]+)/search.*?(\\Wq|as_q)=cache:[^:]*:([^\\s\\+]+)(\\s|\\+)([^&]*).*': 'Google($5) [Cache:$3]', // '^http://216.239.\\d+.\\d+/.*?(\\Wq|as_q)=cache:[^:]*:([^\\s\\+]+)(\\s|\\+)([^&]*).*': 'Google($4) [Cache:$2]', // '^http://\\w+.google.([^/]+)/.*?(\\Wq|as_q)=([^&]*).*': 'Google($3)', // '^http://216.239.\\d+.\\d+/.*?(\\Wq|as_q)=([^&]*).*': 'Google($2)', // '^http://google/search.*?\\Wq=([^&]*).*': 'Google($1)', '^http://([^\.]*\.)?search.yahoo.(com|co\\.jp)/.*?p=([^&]*).*': 'Yahoo($3)', '^http://new.search.yahoo.([^/]+)/.*\\Wp=([^&]*).*': 'Yahoo($2)', '^http://websearch.yahoo.(com|co\\.jp)/.*?p=([^&]*).*': 'Yahoo($2)', '^http://(www|search|ocn(search)?|blog|mixi.search).goo.ne.jp/.*?MT=([^&]*).*': 'goo($3)', '^http://.*?livedoor.com/.*?search\\?q=([^&]*).*': 'livedoor($1)', '^http://.*search.msn(\\.[^/]+)/.*?[\\?&]x(q|MT)=([^&]*).*': 'msn($3)', '^http://.*search.msn.*?[\\?&](q|MT)=([^&]*).*': 'msn($2)', '^http://(www|ocn|apple|so-net|dion|odn|hi-ho|sleipnir).excite.co.jp/.*?(search|s)=([^&]*).*': 'excite($3)', '^http://.*?matome.jp/(tag|keyword)/(.*?)(.html)?$': 'matome.jp($2)', '^http://(search.)?(www.)?infoseek.co.jp/.*?qt=([^&]*).*': 'Infoseek($3)', '^http://search.odn.ne.jp/.*?(QueryString|key)=([^&]*).*': 'ODN($2)', '^http://.*?lycos.(co\\.jp|com)/?.*(query|qt?)=([^&]*).*': 'Lycos($3)', '^http://search.fresheye.com/.*?kw=([^&]*).*': 'FreshEye($1)', '^http://(a?search|www).nifty.com/.*?(q|Text)=([^&]*).*': '@nifty($3)', '^http://odin.ingrid.org/.*?key=([^&]*).*': 'ODiN($1)', '^http://search.naver.co.jp/search.naver.*?query=([^&]*).*': 'NAVER($1)', '^http://cgi.search.biglobe.ne.jp/cgi-bin/.*?q=([^&]*).*': 'BIGLOBE($1)', '^http://www.ceek.jp/.*q=([^&]*).*': 'ceek.jp($1)', '^http://.*?.aol.com/.*query=([^&]*).*': 'AOL Search($1)', '^http://www.euroseek.com/.*string=([^&]*).*': 'euroseek.com($1)', // '^http://(www.)?technorati.jp/search/search.html.*\\?.*query=([^&]*).*': 'technorati.jp($2)', '^http://(www.)?technorati.jp/search/([^\?&]*).*': 'technorati.jp($2)', '^http://(www.)?technorati.com/search/([^\\?&]*).*': 'technorati.com($2)', '^http://(www.)?technorati.com/tags?/([^\\?&]*).*': 'technorati.com(Tags:$2)', '^http://www.yahoogle.jp/(.*).html': 'yahoogle($1)', '^http://ask.jp/blog.asp\\?.*?q=([^&]*).*': 'ask.jp($1)', '^http://(cybozu|duogate).excite.co.jp/search.gw\\?.*search=([^&]*).*': 'excite($2)', '^http://search.blogger.com/.*\\?.*?q=([^&]*).*': 'blogger($1)', '^http://bulkfeeds.net/.*?q=([^&]*).*': 'bulkfeeds($1)', // '^http://crooz.jp/ex/([^/]+)/k/proxy_i.jsp\\?(.*)query=([^&]*).*': '$1($3)', // '^http://crooz.jp/k/search.jsp\\?.*query=([^&]*).*': 'crooz($1)', '^http://bst.blogpeople.net/search_result.jsp?.*keyword=([^&]*)': 'blogpeople($1)', '^(http://trendlink.mirailab.com/.*)': 'trendlink($1)', '^(http://tl.milabo.net/.*)': 'trendlink($1)', // '^(http://animemo.seesaa.net/article/.*)': 'animemo($1)', '^(http://www.blognavi.com/entry/.*)': 'blognavi($1)', '^(http://(www.)?1470.net/bm/urlinfo/.*)': 'blogmap($1)', // '^(http://clipsubject.com/ac/.*)': 'clipsubject($1)', '^http://ezsch.ezweb.ne.jp/search/.*query=([^&]*).*': 'ezsch($1)', '^http://www.namaan.net/result?.*query=([^&]*).*': 'NAMAAN($1)', // åããã¼ã // '^http://([^\\?/]+).*\\?.*&?(q|p|search|key)=([^&]*).*': '$1($3)', }; // asinæ¤ç´¢ // var patAsin = { '^http://(d|diary).hatena.ne.jp/asin(mobile|diary)?/([^/?]+).*': 'ASIN:$3', '^http://(www.)?1470.net/bm/asininfo/([0-9A-Z]+)': 'ASIN:$2', '^http://allconsuming.jp/item.cgi\\?asin=([0-9A-Z]+)': 'ASIN:$1', }; // JAN/EANæ¤ç´¢ // var patEan = { '^http://(d|diary).hatena.ne.jp/ean/([^/?]+).*': 'EAN:$2', }; // privateãªãªã³ã¯ // var patPrivate = { '^http://127.0.0.1(:[0-9]+)?/(.*)': 'localhost($2)', '^http://localhost(:[0-9]+)?/(.*)': 'localhost($2)', '^http://192.168.[0-9]+.[0-9]+(:[0-9]+)?/(.*)': 'local IP($2)', '^http://(www.)?bloglines.com/myblogs_display\\?(.*)': 'bloglines($2)', '^http://www.google.com/reader(/.*)': 'Google Reader($1)', '^http://mail.google.com/mail/(.*)': 'Gmail($1)', '^http://reader.livedoor.com(/.*)': 'LDR($1)', }; // ãã®ä»ã®ãªã³ã¯ // var patOther = { }; var replacePatternList = [ { category: 'Asin', pattern: patAsin, }, { category: 'EAN', pattern: patEan }, { category: 'Keyword', pattern: patKeywords, }, { category: 'Diary', pattern: patDiaries, }, { category: 'Antenna', pattern: patAntennae, }, { category: 'Bookmark', pattern: patBookmarks, }, { category: 'RSS', pattern: patRSS, }, { category: 'Idea', pattern: patIdeas, }, { category: 'Search', pattern: patSearches, }, { category: 'Others(Hatena)', pattern: patHatena, }, { category: 'Others', pattern: patOther, }, { category: 'Private', pattern: patPrivate, }, ]; /*===== è¨å®çµãã =====*/ Object.prototype.keys = function() { var arrKeys = new Array(); for (var key in this) { if (this.hasOwnProperty(key)) arrKeys.push(key); } return arrKeys; } function makeIteratorFromList(ref_func, iter_num, offset) { if (typeof offset == 'undefined') offset = 0; var idx = offset; var idx_end = offset + iter_num; return function() { return (idx < idx_end) ? ref_func(idx++) : null; } } function makeArrayFromIterator(it_func) { var ret = new Array(); var obj; while (obj = it_func()) { ret.push(obj); } return ret; } // ref: http://piro.sakura.ne.jp/xul/tips/x0032.html // ref: http://lowreal.net/logs/2006/03/16/1 function createNSResolver(evaluator, nodeResolver) { const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'; const XHTMLNS = 'http://www.w3.org/1999/xhtml'; const XLinkNS = 'http://www.w3.org/1999/xlink'; const XMLNS = 'http://www.w3.org/XML/1998/namespace'; var defaultRresolver = evaluator.createNSResolver(nodeResolver); var resolver = { defaultNS: null, defaultPrefix: '', lookupNamespaceURI : function(aPrefix) { switch (aPrefix) { case 'xul': return XULNS; case 'xml': return XMLNS; case 'html': case 'xhtml': return XHTMLNS; case 'xlink': return XLinkNS; default: // return ''; return (this.defaultNS != null) ? this.defaultNS : defaultResolver.lookupNamespaceURI(this.defaultPrefix); } } }; return resolver; } // ref: http://piro.sakura.ne.jp/xul/tips/x0032.html function getNodesFromXPath(aXPath, aContextNode, aType) { const type = aType || XPathResult.ANY_TYPE; const xmlDoc = aContextNode ? aContextNode.ownerDocument : document ; const context = aContextNode || xmlDoc.documentElement; var resolver = createNSResolver(xmlDoc, context); var expression = xmlDoc.createExpression(aXPath, resolver); return expression.evaluate(context, type, null); } // ref: http://lowreal.net/logs/2006/03/13/3 // ref: http://lowreal.net/logs/2006/03/16/1 function $X(exp, context, type) { // type = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE; // type = XPathResult.ORDERED_NODE_ITERATOR_TYPE; // var singleValueWrapper = function(val) { return (type != null) ? val : [ val ] }; var result = getNodesFromXPath(exp, context, type); switch (result.resultType) { case XPathResult.NUMBER_TYPE: return result.numberValue; case XPathResult.STRING_TYPE: return result.stringValue; case XPathResult.BOOLEAN_TYPE: return result.booleanValue; case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: case XPathResult.ORDERED_NODE_ITERATOR_TYPE: var it = function() { return result.iterateNext(); }; return makeArrayFromIterator(it); case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE: case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE: var it = makeIteratorFromList(function(i) { return result.snapshotItem(i) }, result.snapshotLength); return makeArrayFromIterator(it); default: throw 'ERROR: unknown resultType'; } } function replaceByPattern(replacePatternList, text) { for (var pat_idx = 0, pat_len = replacePatternList.length; pat_idx < pat_len; pat_idx++) { var cat = replacePatternList[pat_idx].category; var pattern_list = replacePatternList[pat_idx].pattern; for (var patFrom in pattern_list) { if (! pattern_list.hasOwnProperty(patFrom)) continue; var patTo = pattern_list[patFrom]; var text2 = text.replace(RegExp(patFrom), patTo); if (text != text2) { text = text2; // text = text2.replace(/\+/g, ' '); category = cat; return { category: cat, text: text }; } } } return { category: 'Others', text: text }; } var divReferList = $X('//div[@id="referer-list"]')[0]; if (!divReferList) return; // refererItemHref[ã¢ã³ã«ã¼ããã¹ã] = [ãªã³ã¯å 1, ãªã³ã¯å 2, ...] var refererItemHref = new Object(); // refererItemCount[ã«ãã´ãª][ã¢ã³ã«ã¼ããã¹ã] var refererItemCount = new Object(); function registerRefererItem(category, text, href) { if (!refererItemCount[category]) refererItemCount[category] = new Object(); if (!refererItemCount[category][text]) refererItemCount[category][text] = 0; refererItemCount[category][text] += refererCount; if (!refererItemHref[text]) refererItemHref[text] = new Array(); refererItemHref[text].push(href); } function addCategory(divReferList, cat) { var aAssoc = refererItemCount[cat]; var keys = aAssoc.keys().sort(function(a, b) { var cmp = aAssoc[b] - aAssoc[a]; if (cmp == 0) { if (a < b) cmp = -1; else if (a > b) cmp = 1; } return cmp; }); var h4 = document.createElement('h4'); h4.appendChild(document.createTextNode(cat)); divReferList.appendChild(h4); var ulRefCategory = document.createElement('ul'); for (var k = 0; k < keys.length; k++) { var key = keys[k]; var liItem = document.createElement('li'); var text = document.createTextNode(refererItemCount[cat][key] + ' '); liItem.appendChild(text); var a = document.createElement('a'); a.href = refererItemHref[key][0]; a.textContent = key; liItem.appendChild(a); for (var i = 1; i < refererItemHref[key].length; i++) { var text = document.createTextNode(' '); liItem.appendChild(text); var a = document.createElement('a'); a.href = a.title = refererItemHref[key][i]; a.textContent = i; liItem.appendChild(a); } ulRefCategory.appendChild(liItem); } divReferList.appendChild(ulRefCategory); return ulRefCategory; } // ãªãã¡ã©æ å ±ãéãã var liRefererItems = $X('./ul/li', divReferList); if (liRefererItems.length == 0) return; for (var li_idx = 0, li_len = liRefererItems.length; li_idx < li_len; li_idx++) { var refererCount; if (liRefererItems[li_idx].textContent.match(/^\s*(\d+)\s+/)) refererCount = parseInt(RegExp.$1); if (!refererCount) { GM_log('refererCount is null'); continue; } // ãªãã¡ã©ã¸ã®ã¢ã³ã«ã¼ var aRefererItem = $X('./a', liRefererItems[li_idx])[0]; if (!aRefererItem) { // GM_log('aRefererItem is null'); continue; } var replaceResult = replaceByPattern(replacePatternList, aRefererItem.text); var text = replaceResult.text; var category = replaceResult.category; registerRefererItem(category, text, aRefererItem.href); } // ãªã³ã¯å ãªã¹ããåé¤ var ulRefererItems = $X('./ul', divReferList); if (!ulRefererItems) return; for (var ul_idx = 0, ul_len = ulRefererItems.length; ul_idx < ul_len; ul_idx++) { divReferList.removeChild(ulRefererItems[ul_idx]); } // ããªã³ã¯å ãåé¤ããããã¿ã³ãåé¤ var deleteReferer = $X('//input[@name = "deletereferer"]')[0]; if (deleteReferer) { deleteReferer.parentNode.removeChild(deleteReferer); } // ã«ãã´ãªæ¯ã«ãªã³ã¯å ãªã¹ãã追å var ulList = new Object(); for (var cat_idx = 0, cat_len = replacePatternList.length; cat_idx < cat_len; cat_idx++) { var cat = replacePatternList[cat_idx].category; if (refererItemCount[cat]) ulList[cat] = addCategory(divReferList, cat); } /*===== ãªã³ã¯å ã®ãã¼ã¸ã¿ã¤ãã«ã追å ããå¦ç =====*/ function TitleUpdater(ext) { for (var prop in ext) { if (ext.hasOwnProperty(prop)) { this[prop] = ext[prop]; } } }; TitleUpdater.prototype = { getUrlFromAnchor: function(anchor) { return null; }, getTitleFromText: function(text) { return null; }, update: function (ulList) { var links = $X('.//li//a[position()=1]', ulList); for (var i = 0; i < links.length; i++) { var anchor = links[i]; var url = this.getUrlFromAnchor(anchor); if (url) this.setTitleAsync(anchor, url); } }, setTitleAsync: function(anchor, url) { const getTitleFromText = this.getTitleFromText; GM_xmlhttpRequest({ method: 'GET', url: url, onload: function(responseDetails) { var title = getTitleFromText(responseDetails.responseText); if (title) { var text = document.createTextNode(''); text.textContent = ' - ' + title; anchor.parentNode.appendChild(text); } } }); }, }; if (ulList['Asin']) { var titleUpdater = new TitleUpdater({ getUrlFromAnchor: function(anchor) { if (anchor.textContent.match(/ASIN:(.*)/)) { var asin = RegExp.$1; return 'http://d.hatena.ne.jp/asin/' + asin; } return null; }, getTitleFromText: function(text) { if (text.match(/<h1>(.*)<\/h1>/)) { return RegExp.$1; } return null; }, }); titleUpdater.update(ulList['Asin']); } if (ulList['EAN']) { var titleUpdater = new TitleUpdater({ getUrlFromAnchor: function(anchor) { if (anchor.textContent.match(/EAN:(.*)/)) { var ean = RegExp.$1; return 'http://d.hatena.ne.jp/ean/' + ean; } return null; }, getTitleFromText: function(text) { if (text.match(/<h1>(.*)<\/h1>/)) { return RegExp.$1; } return null; }, }); titleUpdater.update(ulList['EAN']); } if (ulList['Search'] || ulList['Bookmark']) { var titleUpdater = new TitleUpdater({ getUrlFromAnchor: function(anchor) { if (anchor.textContent.match(/(http:\/\/[^\)]+)/)) { // var url = RegExp.$1; var url = anchor.href; return url; } return null; }, getTitleFromText: function(text) { if (text.match(/<title>([^<]+)<\/title>/)) { return RegExp.$1; } return null; }, }); if (ulList['Search']) titleUpdater.update(ulList['Search']); if (ulList['Bookmark']) titleUpdater.update(ulList['Bookmark']); } })();
åèãªã³ã¯
- Greasemonkeyではてなダイアリーのリンク元を整形 | weblog | 東京嫉妬
- Greasemonkeyではてなダイアリーのリンク元を整形 #2 | weblog | 東京嫉妬
- JS の XPath < 13 < March < 2006 < nulog, NULL::something : out of the headphone
- XPath, $X function, NSResolver < 16 < March < 2006 < nulog, NULL::something : out of the headphone
- XUL Apps > Tips > DOM3 XPathをノードの検索に活用する - outsider reflex