// ==UserScript== // @name google reader full feed changer // @namespace http://blog.fkoji.com/ // @include http://www.google.*/reader/* // @include https://www.google.*/reader/* // @version 0.71 // ==/UserScript== var SITE_INFO = [ { url: 'www.eeo.com.cn', xpath: '(//div[@id="text_content"]|//div[@class="content link12hui"])', }, { url: 'www.ftchinese.com', xpath: '//div[@class="content"]', }, { url: 'www.infoq.com', xpath: '//div[@class="box-content-5"]', }, { url: 'www.hbrchina.com', xpath: '//div[@id="txtcontent"]', charset: 'gb2312' }, { url: 'blog.sina.com.cn', xpath: '//div[@id="articleBody"]', }, { url: 'http://news.163.com', xpath: '//div[@id="endText"]', charset: 'gb2312' } /* { url: '', xpath: '', charset: '' } */ ]; var AUTO_FETCH = false; var SHOW_ENGLISH = false; var DO_ONCE = true; var ON_GET = false; var FullFeed = {}; FullFeed.link = ''; FullFeed.getFocusedLink = function() { return getStringByXPath('//div[@id="current-entry"]//a[@class="entry-title-link"]/@href'); } FullFeed.getCurrentEntry = function() { var link = this.getFocusedLink(); this.link = link; var body = getFirstElementByXPath('//div[@id="current-entry"]//div[@class="entry-body"]'); if (!body) { body= getFirstElementByXPath('//div[@id="current-entry"]//div[@class="entry-body entry-body-empty"]'); } var source = ''; if (location.href.match(/#stream\/user/)) { source = getStringByXPath('//div[@id="current-entry"]//a[@class="entry-source-title"]/@href'); } else if (location.href.match(/#search\//)) { source = getStringByXPath('//div[@id="current-entry"]//a[@class="entry-source-title"]/@href'); } else if (location.href.match(/#stream\/feed/)) { source = getStringByXPath('//span[@id="chrome-title"]//a/@href'); } if (!source) { return false; } source = decodeURIComponent(source.replace(/^\/reader\/view\/feed\//, '')); var len = SITE_INFO.length; for (var i = 0; i < len; i++) { var reg = new RegExp(SITE_INFO[i].url); if (source.match(reg) || link.match(reg)) { this.request(i, link, body); lock(); break; } } }; FullFeed.request = function(i, link, body) { var mime = 'text/html; charset='; if (SITE_INFO[i].charset) { mime = mime + SITE_INFO[i].charset; } else { mime = mime + 'utf-8'; } GM_xmlhttpRequest({method: "GET", url: link, overrideMimeType: mime, onload: function(r) { var text = r.responseText; text = text.replace(/(<[^>]*?)on(?:(?:un)?load|(?:db)?click|mouse(?:down|up|over|out|move)|key(?:press|down|up)|abort|blur|change|error|focus|re(?:size|set)|select|submit)\s*?=\s*?["'][^"']*?["']/ig, "$1"); var show163 = true; if (link.match('163')) { var comment = text.match('var end_board.+;'); if (comment == null) { show163 = false; } else { eval(comment[0]); var comments = new Array(end_board, end_thread, end_count); } // alert(comments.length); // var carray = "var comments = new " + comment.replace('reply_setHidden','Array'); // eval(carray); } text = text.replace(/<\s*?script[^>]*?>[\s\S]*?<\s*?\/script\s*?>/ig, ""); var htmldoc = createHTMLDocumentByString(text); var contents = getFirstElementByXPath(SITE_INFO[i].xpath, htmldoc); if (contents == null) return; while (body.firstChild && !SHOW_ENGLISH) { body.removeChild(body.firstChild); } if (link.match('ftchinese') && text.match('showenglish')) SHOW_ENGLISH = true; if (!contents.length) { if (SHOW_ENGLISH) body.insertBefore(addTargetAttr(relativeToAbsolute(contents, link)), body.firstChild); else body.appendChild(addTargetAttr(relativeToAbsolute(contents, link))); if (link.match('163') && show163){ var pElement = document.createElement("a"); pElement.setAttribute("target","_blank"); pElement.setAttribute("style","color:#ba2636;text-decoration:none;font-size:12px;"); pElement.setAttribute("href","http://comment.news.163.com/"+comments[0]+"/"+comments[1]+".html"); pElement.innerHTML="跟帖 "+comments[2]+" 条"; var eElement = pElement.cloneNode(true); body.insertBefore(pElement, body.firstChild); body.appendChild(eElement); } if (r.status == 200 && SHOW_ENGLISH && DO_ONCE) {FullFeed.request(i, link+"&lang=en", body);DO_ONCE = false;} return; } // array for (var num = 0; num < contents.length; num++) { body.appendChild(addTargetAttr(relativeToAbsolute(contents[num], link))); } }, onreadystatechange: function(r){if (r.status != 200) ON_GET = false; else ON_GET = true;}}); }; function initial(){ setTimeout(initial,2000); if (ON_GET) { DO_ONCE = true; SHOW_ENGLISH = false; } } function relativeToAbsolute(node, link) { var imgs = getElementsByXPath('//img', node); if (imgs.length) { for (var i = 0; i < imgs.length; i++) { var src = imgs[i].getAttribute('src'); if (src) { imgs[i].setAttribute('src', toAbsolutePath(src, link)); } } } var anchor = getElementsByXPath('//a', node); if (anchor.length) { for (var i = 0; i < anchor.length; i++) { var href = anchor[i].getAttribute('href'); if (href) { anchor[i].setAttribute('href', toAbsolutePath(href, link)); } } } return node; } function addTargetAttr(node) { var anchors = getElementsByXPath('//a', node); if (!anchors) { return false; } for (var i = 0; i < anchors.length; i++) { anchors[i].setAttribute('target', '_blank'); } return node; } function createHTMLDocumentByString(str) { var html = str.replace(/<!DOCTYPE.*?>/, '').replace(/<html.*?>/, '').replace(/<\/html>.*/, '') var htmlDoc = document.implementation.createDocument(null, 'html', null) var fragment = createDocumentFragmentByString(html) htmlDoc.documentElement.appendChild(htmlDoc.importNode(fragment, true)) return htmlDoc } function createDocumentFragmentByString(str) { var range = document.createRange() range.setStartAfter(document.body) return range.createContextualFragment(str) } function getStringByXPath(xpath, node) { var node = node || document var doc = node.ownerDocument ? node.ownerDocument : node var str = doc.evaluate(xpath, node, null, XPathResult.STRING_TYPE, null) return (str.stringValue) ? str.stringValue : '' } function getElementsByXPath(xpath, node) { var node = node || document var doc = node.ownerDocument ? node.ownerDocument : node var nodesSnapshot = doc.evaluate(xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null) var data = [] for (var i = 0; i < nodesSnapshot.snapshotLength; i++) { data.push(nodesSnapshot.snapshotItem(i)) } return (data.length >= 1) ? data : null } function getFirstElementByXPath(xpath, node) { var node = node || document var doc = node.ownerDocument ? node.ownerDocument : node var result = doc.evaluate(xpath, node, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null) return result.singleNodeValue ? result.singleNodeValue : null } function toAbsolutePath(url, base) { // absolute path if (url.match(/^https?:\/\//)) { return url; } var head = base.match(/^https?:\/\/[^\/]+\//)[0]; if (url.indexOf('/') == 0) { return head + url; } var basedir = base.replace(/\/[^\/]+$/, '/'); if (url.indexOf('.') == 0) { while (url.indexOf('.') == 0) { if (url.substr(0, 3) == '../') { basedir = basedir.replace(/\/[^\/]+\/$/, '/'); } url = url.replace(/^\.+\//, ''); } } return basedir + url; } function getPageFromURL(url){ return url.replace(/^https?:\/\/[^\/].+\//, ''); } if (AUTO_FETCH) { var interval = window.setInterval( function() { var focusedLink = FullFeed.getFocusedLink(); if (focusedLink != FullFeed.link) { FullFeed.getCurrentEntry(); } }, 500 ); } document.addEventListener( 'keydown', function(event) { var key = String.fromCharCode(event.keyCode); if (key.toLowerCase() == 'z') { FullFeed.getCurrentEntry(); } }, false ); document.addEventListener( 'keydown', function(event) { var key = String.fromCharCode(event.keyCode); var name = "chrome-lhn-toggle"; if (key.toLowerCase() == 'q') { var evt = document.createEvent("MouseEvents"); evt.initEvent("click", true, true); document.getElementById(name).dispatchEvent(evt); } }, false ); document.addEventListener( 'keydown', function(event) { var key = String.fromCharCode(event.keyCode); var name = "show-new"; var showNew = document.getElementById("show-new"); var showAll = document.getElementById("show-all"); if (key.toLowerCase() == 'w') { var evt = document.createEvent("MouseEvents"); evt.initEvent("click", true, true); if (showNew.className=="unselectable link"){ showNew.dispatchEvent(evt); }else{ showAll.dispatchEvent(evt); } } }, false ); initial();