Skip to content

Commit

Permalink
first import.
Browse files Browse the repository at this point in the history
  • Loading branch information
mattn committed Sep 7, 2009
0 parents commit 7253309
Show file tree
Hide file tree
Showing 4 changed files with 362 additions and 0 deletions.
Binary file added google_reader_full_feed.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 53 additions & 0 deletions google_reader_full_feed.html
@@ -0,0 +1,53 @@
<script type="text/javascript">
window.onload = function() {
chrome.self.onConnect.addListener(function(port) {
port.onMessage.addListener(function(data, con) {
switch(data.task) {
case "siteinfo":
{
var req = new XMLHttpRequest();
req.open('GET', 'http://wedata.net/databases/LDRFullFeed/items.json', true);
req.onload = function(res) {
var siteinfos = eval(req.responseText)
.map(function(i) { return i.data })
.sort(function(lhs, rhs) { return rhs.priority - lhs.priority });
data.result = true;
data.content = siteinfos;
con.postMessage(data);
};
req.onerror = function(res) {
data.result = false;
data.content = [];
con.postMessage(data);
};
req.send(null);

document.getElementById('grff').onclick = function() {
con.postMessage({'result':true, 'task':'update-siteinfo'});
}
}
break;
case "fullfeed":
{
var req = new XMLHttpRequest();
req.open('GET', data.url, true);
req.onload = function(res) {
data.result = true;
data.content = req.responseText;
con.postMessage(data);
};
req.onerror = function(res) {
data.result = false;
con.postMessage(data);
};
req.send(null);
}
break;
}
});
});
}
</script>
<div class="toolstrip-button">
<img src="google_reader_full_feed.gif" id="grff" title="google reader full feed for chrome"/>
</div>
292 changes: 292 additions & 0 deletions google_reader_full_feed.js
@@ -0,0 +1,292 @@
if (window != top) return;

// simple version of $X
// $X(exp);
// $X(exp, context);
// @source http://gist.github.com/3242.txt
// @author id:os0x
function $X (exp, context) {
context || (context = document);
var expr = (context.ownerDocument || context).createExpression(exp, function (prefix) {
return document.createNSResolver(context.documentElement || context).lookupNamespaceURI(prefix) ||
context.namespaceURI || document.documentElement.namespaceURI || "";
});

var result = expr.evaluate(context, XPathResult.ANY_TYPE, null);
switch (result.resultType) {
case XPathResult.STRING_TYPE : return result.stringValue;
case XPathResult.NUMBER_TYPE : return result.numberValue;
case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
// not ensure the order.
var ret = [], i = null;
while (i = result.iterateNext()) ret.push(i);
return ret;
}
return null;
}

function rel2abs(resolver, htmldoc){
$X("descendant-or-self::a[@href]", htmldoc)
.forEach(function(elm) {
elm.setAttribute("href", resolver(elm.getAttribute("href")));
});
$X("descendant-or-self::*[self::img[@src] or self::embed[@src]]", htmldoc)
.forEach(function(elm) {
elm.setAttribute("src", resolver(elm.getAttribute("src")));
});
$X("descendant-or-self::object[@data]", htmldoc)
.forEach(function(elm) {
elm.setAttribute("data", resolver(elm.getAttribute("data")));
});
}

var remove_risks = function(htmldoc){
var attr = "allowscriptaccess";
$X("descendant-or-self::embed[@allowscriptaccess]", htmldoc)
.forEach(function(elm){
elm.setAttribute(attr, "never");
});
$X("descendant-or-self::param", htmldoc)
.forEach(function(elm){
if(!elm.getAttribute("name") || elm.getAttribute("name").toLowerCase().indexOf(attr) < 0) return;
elm.setAttribute("value", "never");
});
}

function filter(a, f) {
for (var i = a.length; i --> 0; f(a[i]) || a.splice(i, 1));
}

function parse(str, url) {
try {
var htmldoc = document.implementation.createHTMLDocument('fullfeed');
var df = $CF(str);
nl = df.childNodes;
htmldoc.body.appendChild(df);
remove_risks(htmldoc);
var resolver = path_resolver(url);
rel2abs(resolver, htmldoc);
return htmldoc;
} catch(e) {
console.info(e);
throw 'Parse Error';
}
}

function path_resolver(base) {
var top = base.match(/^https?:\/\/[^\/]+/)[0];
var current = base.replace(/\/[^\/]+$/, '/');
return function(url){
if (url.match(/^https?:\/\//)) {
return url;
} else if (url.indexOf("/") === 0) {
return top + url;
} else {
var result = current;
if(url.indexOf(".") === 0){
var count = 15;// 無限ループ防止用. 15回も../や./使ってるURLはさすがにないだろということで.
while(url.indexOf(".") === 0 && !(--count === 0)){
if(url.substring(0, 3) === "../")
result = result.replace(/\/[^\/]+\/$/,"/");
url = url.replace(/^\.+\/?/,"")
}
}
return result + url;
}
}
}

var $CF = (function(){
var range = document.createRange();
range.selectNodeContents(document.body);
return function(str){
return range.createContextualFragment(str);
}
})();

// copied from LDRize (c) id:snj14
function addStyle(css,id) { // GM_addStyle is slow
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'data:text/css,' + escape(css);
document.body.appendChild(link);
}

var FlashMessage = new function(){
addStyle([
'#FLASH_MESSAGE{',
'position : fixed;',
'font-size : 200%;',
'z-index : 10000;',
'padding : 20px 50px 20px 50px;',
'left : 50%;',
'top : 50%;',
'margin : -1em;',
'background-color : #444;',
'color : #FFF;',
'-webkit-border-radius: 0.3em;',
'min-width : 1em;',
'text-align : center;',
'} '
].join(''))
var opacity = 0.9;
var flash = document.createElement('div');
flash.id = 'FLASH_MESSAGE';
hide(flash);
document.body.appendChild(flash);
var canceler;
this.showFlashMessageWindow = function (string, duration) {
duration = duration || 400;
canceler && canceler();
flash.innerHTML = string;
//flash.style.MozOpacity = opacity;
flash.style.opacity = opacity;
show(flash);
flash.style.marginLeft = (-(flash.offsetWidth/2))+'px';

canceler = callLater(function(){
canceler = tween(function(value){
//flash.style.MozOpacity = opacity * (1-value);
flash.style.opacity = opacity * (1-value);
}, 100, 5);
}, duration);
};

// ----[Utility]-------------------------------------------------
function callLater(callback, interval){
var timeoutId = setTimeout(callback, interval);
return function(){
clearTimeout(timeoutId)
}
}
function tween(callback, span, count){
count = (count || 20);
var interval = span / count;
var value = 0;
var calls = 0;
var intervalId = setInterval(function(){
callback(calls / count);

if(count == calls){
canceler();
return;
}
calls++;
}, interval);
var canceler = function(){
clearInterval(intervalId)
hide(flash)
}
return canceler;
}
function hide(target){
target.style.display='none';
}
function show(target, style){
target.style.display=(style || '');
}
};

function message (mes){
FlashMessage.showFlashMessageWindow(mes, 1000);
}

var port = chrome.extension.connect();
port.onMessage.addListener(function(data) {
try {
if (data.result) {
switch (data.task) {
case "update-siteinfo":
{
message("fetching siteinfos: ...");
port.postMessage({'task': 'siteinfo'});
}
break;
case "siteinfo":
{
siteinfos = data.content;
message("fetching siteinfos: done");
}
break;
case "fullfeed":
{
message("fetching fullfeed: done");
var text = data.content;
text = text.replace(/(<[^>]+?[\s"'])on(?:(?:un)?load|(?:dbl)?click|mouse(?:down|up|over|move|out)|key(?:press|down|up)|focus|blur|submit|reset|select|change)\s*=\s*(?:"(?:\\"|[^"])*"?|'(\\'|[^'])*'?|[^\s>]+(?=[\s>]|<\w))(?=[^>]*?>|<\w|\s*$)/gi, "$1");
text = text.replace(/<iframe(?:\s[^>]+?)?>[\S\s]*?<\/iframe\s*>/gi, "");
var htmldoc = parse(text, data.url);
var exp = 'id("current-entry")//div[contains(concat(" ", @class, " "), " entry-body ")]';
var body = $X(exp)[0]
while (body.firstChild) body.removeChild(body.firstChild);
var entry = $X(lastItem.siteinfo.xpath, htmldoc);
var content = document.createDocumentFragment();
entry.map(function(i) {
try {
i = document.adoptNode(i, true);
} catch (e) {
i = document.importNode(i, true);
}
content.appendChild(i);
});
body.appendChild(content);
}
break;
}
}
} catch(e) {
message("failed to task: " + data.task);
}
});

var siteinfos = [];
var lastItem = {};

function fullfeed() {
}

var timer = setTimeout(function() {
if (timer) clearTimeout(timer);
try {
var exp = 'id("current-entry")//a[contains(concat(" ", @class, " "), " entry-title-link ")]';
var url = $X(exp)[0].href;
if (lastItem.url == url) throw "nothing to do..."
lastItem.url = url;

for (var n = 0; n < siteinfos.length; n++) {
if ((new RegExp(siteinfos[n].url)).test(url)) {
var icon = document.createElement('span');
icon.title = "ready to fetch full entry";
icon.innerHTML = '<img src="' + chrome.extension.getURL('google_reader_full_feed.gif') + '" style="cursor: pointer;"/>';
icon.addEventListener('click', function() {
message("fetching fullfeed: ...");
port.postMessage({'task': 'fullfeed', 'url': lastItem.url});
}, false);
icon.className = 'chrome_grff_checked';
var container = $X('id("current-entry")//a[contains(concat(" ", @class, " "), " entry-title-link ")]')[0].parentNode;
container.appendChild(document.createTextNode(' '));
container.appendChild(icon);
lastItem.siteinfo = siteinfos[n];
break;
}
}
} catch(e) {}
timer = setTimeout(arguments.callee, 200);
});

setTimeout(function() {
message("fetching siteinfos: ...");
port.postMessage({'task': 'siteinfo'});
/*
document.addEventListener('keyup', function(e) {
if (e.keyCode == w.KeyEvent.DOM_VK_Z) {
var exp = 'id("current-entry")//a[contains(concat(" ", @class, " "), " entry-title-link ")]';
var url = $X(exp)[0].href;
if (lastItem.url != url) return;
message("fetching fullfeed: ...");
port.postMessage({'task': 'fullfeed', 'url': lastItem.url});
}
}, false);
*/
}, 500);

17 changes: 17 additions & 0 deletions manifest.json
@@ -0,0 +1,17 @@
{
"name": "google reader full feed",
"description": "google reader full feed for google chrome. show full story of the current entry in google reader.",
"version": "0.0.1",
"permissions": [
"http://*/*"
],
"toolstrips": [ "google_reader_full_feed.html" ],
"content_scripts": [
{
"js": [ "google_reader_full_feed.js" ],
"matches": [
"http://www.google.com/reader/*"
]
}
]
}

0 comments on commit 7253309

Please sign in to comment.