var PLUGIN_INFO = xml` SBM Comments Viewer List show Social Bookmark Comments ソーシャル・ブックマーク・コメントを表示します 0.2.6 3.8.3.1 https://raw.githubusercontent.com/vimpr/vimperator-plugins/master/sbmcommentsviewer.js || viewSBMComments [url] [options] url : 省略時は現在のURL options: -f, -format : 出力時のフォーマット(${'`'},'区切りのリスト) (default: id,timestamp,tags,comment) let g:def_sbm_format = ... で指定可能 -t, -type : 出力するSBMタイプ (default: hdl) let g:def_sbms = ... で指定可能 -c, -count : ブックマーク件数のみ出力 -b, -browser: バッファ・ウィンドウではなくブラウザに開く TODO:まだ出来てない ||< == 指定可能フォーマット == id, timpstamp, tags, comment == SBMタイプ == - h : hatena bookmark - d : Delicious - l : livedoor clip - z : Buzzurl - t : Topsy - T : Twitter - XXX:今後増やしていきたい >|| e.g.) :viewSBMComments http://d.hatena.ne.jp/teramako/ -t hdl -f id,comment -c ||< == 備考 == 一度取得したものは(30分ほど)キャッシュに貯めてますので何度も見直すことが可能です。 粋なコマンド名募集中 ]]> `; liberator.plugins.sbmCommentsViewer = (function(){ var isFilterNoComments = liberator.globalVariables.sbm_comments_viewer_filter_nocomments || false; /** * SBMEntry Container {{{ * @param {String} type * @param {Number} count * @param {Object} extra * extra = { * faviconURL, * pageURL * } */ function SBMContainer(type, count, extra){ //{{{ this.type = type; this.count = count || 0; this.entries = []; if (extra){ this.faviconURL = extra.faviconURL || ''; this.pageURL = extra.pageURL || ''; } } //}}} SBMContainer.prototype = { //{{{ add: function(id, timestamp, comment, tags, extra){ this.entries.push(new SBMEntry( id, timestamp, comment, tags, extra )); }, toHTML: function(format, countOnly){ var label = xml` ${this.faviconURL ? xml`` : ``} ${manager.type[this.type] + ' ' + this.count + '(' + this.entries.length + ')'} ${this.pageURL ? xml`${this.pageURL}` : ``} `; if (countOnly){ return label; } else { let html = xml``; let self = this; html = xml`${html}${(function(){ var div = xml``; self.entries.forEach(function(e){ if (isFilterNoComments && !e.comment) return; div = xml`${div}${e.toHTML(format)}`; }); return div; })()}`; html = xml`
  • ${label}
  • ${html}
    `; return html; } } }; //}}} // }}} /** * SBM Entry {{{ * @param {String} id UserName * @param {String|Date} timestamp * @param {String} comment * @param {String[]} tags * @param {Object} extra * extra = { * userIcon * link * } */ function SBMEntry(id, timestamp, comment, tags, extra){ //{{{ this.id = id || ''; this.timeStamp = timestamp instanceof Date ? timestamp : null; this.comment = comment || ''; this.tags = tags || []; if (extra){ this.userIcon = extra.userIcon || null; this.link = extra.link || null; } } //}}} SBMEntry.prototype = { //{{{ toHTML: function(format){ function makeLink(str, withLink){ let s = str; let result = xml``; while (s.length > 0) { let m = s.match(/(?:https?:\/\/|mailto:)\S+/); if (m) { result = xml`${result}${s.slice(0, m.index)}${m[0]}`; s = s.slice(m.index + m[0].length); } else { result = xml`${result}${s}`; break; } } return result; } var entry = xml``; var self = this; format.forEach(function(colum){ switch(colum){ case 'id': entry = xml`${entry}${self.userIcon ? xml`${self.id}` : `${self.id}`}`; break; case 'timestamp': entry = xml`${entry}${self.formatDate()}`; break; case 'tags': entry = xml`${entry}${self.tags.join(',')}`; break; case 'comment': entry = xml`${entry}${makeLink(self.comment)}`; break; default: entry = xml`${entry}-`; } }); entry = xml`
    ${entry}
    `; return entry; }, formatDate: function(){ if (!this.timeStamp) return ''; var [year,month,day,hour,min,sec] = [ this.timeStamp.getFullYear(), this.timeStamp.getMonth()+1, this.timeStamp.getDate(), this.timeStamp.getHours(), this.timeStamp.getMinutes(), this.timeStamp.getSeconds() ]; return [ year, '/', (month < 10 ? '0'+month : month), '/', (day < 10 ? '0'+day : day), ' ', (hour < 10 ? '0'+hour : hour), ':', (min < 10 ? '0'+min : min), ':', (sec < 10 ? '0'+sec : sec) ].join(''); } }; //}}} //}}} /** * openSBM {{{ * @param {String} url * @param {String} type * @param {String[]} format * @param {Boolean} countOnly * @param {Boolean} openToBrowser */ function openSBM(url, type, format, countOnly, openToBrowser){ var sbmLabel = manager.type[type]; var sbmURL = SBM[sbmLabel].getURL(url); var xhr = new XMLHttpRequest(); xhr.open('GET', sbmURL, true); xhr.onreadystatechange = function(){ if (xhr.readyState == 4){ if (xhr.status == 200){ let sbmContainer = SBM[sbmLabel].parser.call(this, xhr); if (!sbmContainer) return; cacheManager.add(sbmContainer, url, type); if (openToBrowser) manager.open(sbmContainer.toHTML(format,false)); else liberator.echo(sbmContainer.toHTML(format,countOnly)); } else { liberator.echoerr(sbmURL + ' ' + xhr.status); } } }; xhr.send(null); } //}}} /** * getURL と parser メソッドを供えること * getURL は 取得先のURLを返すこと * parser は SBMContainer オブジェクトを返すこと */ var SBM = { //{{{ hatena: { //{{{ getURL: function(url){ var urlPrefix = 'http://b.hatena.ne.jp/entry/jsonlite/?url='; return urlPrefix + encodeURIComponent(url.replace(/%23/g,'#')); }, parser: function(xhr){ //var json = window.eval(xhr.responseText); var json = jsonDecode(xhr.responseText, false); var count = json.bookmarks.length; var c = new SBMContainer('h', json.count, { faviconURL:'http://b.hatena.ne.jp/favicon.ico', pageURL: 'http://b.hatena.ne.jp/entry/' + json.url }); json.bookmarks.forEach(function(bm){ c.add(bm.user, new Date(bm.timestamp), bm.comment, bm.tags, { userIcon: 'http://www.hatena.ne.jp/users/' + bm.user.substring(0,2) + '/' + bm.user +'/profile_s.gif' }); }); return c; } }, //}}} delicious: { //{{{ getURL: function(url){ //var urlPrefix = 'http://del.icio.us/rss/url/'; var urlPrefix = 'http://feeds.delicious.com/rss/url/'; return urlPrefix + getMD5Hash(url); }, parser: function(xhr){ var rss = xhr.responseXML; if (!rss){ liberator.echoerr('Delicious feed is none'); return; } var pageURL, items; try { pageURL = evaluateXPath(rss, '//channel/link')[0].textContent; items = evaluateXPath(rss, '//item'); } catch(e){ liberator.log(e); } var c = new SBMContainer('d', items.length, { faviconURL: 'http://delicious.com/favicon.ico', pageURL: pageURL }); items.forEach(function(item){ var children = item.childNodes; var [id,date,tags,comment,link] = ['','',[],'','']; for (let i=0; i 0 && (url = v[0])) })) { let v = arg['-' + name]; v && f(v); } for (let i=0; i threshold) delete cache[url][type]; } } }, isAvailable: function(url, type){ if (cache[url] && cache[url][type] && new Date() - cache[url][type][0] < threshold) return true; return false; } }; return c_manager; })(); //}}} return manager; })(); // vim: sw=4 ts=4 sts=0 et fdm=marker: