Skip to content

Commit

Permalink
Merge branch 'release/v0.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Muffo committed Aug 31, 2014
2 parents ad38fb1 + 440a3bb commit d6abbd1
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ dist
app/bower_components
test/bower_components
package
*.swp
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
fullyfeedly
FullyFeedly
===========

Chrome extension to display the full content of articles in Feedly


## Usage

The RSS feed of some website contains only a preview of the articles.
FullFeedly is a chrome extensions that allows you to read the full article without leaving Feedly.com

When reading an imcomplete post, simply press the icon of FullFeedly in the URL bar to download the full text.


## Developer

Clone the repository and follow [this guide](http://minimul.com/developing-a-chrome-extension-with-yeoman.html) to build and debug the extension.

The text of the article is extracted using the web API provided by [Boilerpipe](http://boilerpipe-web.appspot.com/).
Binary file modified app/images/icon-128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/images/icon-16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/images/icon-19.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified app/images/icon-38.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 25 additions & 10 deletions app/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "__MSG_appName__",
"version": "0.0.1",
"version": "0.1.0",
"manifest_version": 2,
"description": "__MSG_appDescription__",
"icons": {
Expand All @@ -12,15 +12,30 @@
"scripts": [
"scripts/chromereload.js",
"scripts/background.js"
]
],
"persistent": false
},
"page_action": {
"default_icon": {
"19": "images/icon-19.png",
"38": "images/icon-38.png"
"page_action": {
"default_icon": {
"19": "images/icon-19.png",
"38": "images/icon-38.png"
},
"default_title": "fullyfeedly"
},
"default_title": "fullyfeedly",
"default_popup": "popup.html"
},
"options_page": "options.html"
"content_scripts": [
{
"matches": [
"*://*.feedly.com/*"
],
"js": [
"scripts/content.js"
]
}
],
"permissions": [
"declarativeContent",
"activeTab",
"http://boilerpipe-web.appspot.com/*"
],
"options_page": "options.html"
}
42 changes: 38 additions & 4 deletions app/scripts/background.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,45 @@
'use strict';

chrome.runtime.onInstalled.addListener(function (details) {
console.log('previousVersion', details.previousVersion);
console.log('FullyFeedly installed: previousVersion', details.previousVersion);
});

chrome.tabs.onUpdated.addListener(function (tabId) {
chrome.pageAction.show(tabId);

function printResponse(response) {
console.log('Content response:\n' + response);
}

/* Regex-pattern to check URLs against.
It matches URLs like: http[s]://[...]feedly.com[...] */
var urlRegex = /^https?:\/\/(?:[^\.]+\.)?feedly\.com/;

// When the browser-action button is clicked...
chrome.pageAction.onClicked.addListener(function(tab) {
// ...check the URL of the active tab against our pattern and...
if (urlRegex.test(tab.url)) {
// ...if it matches, send a message specifying a callback too
chrome.tabs.sendMessage(tab.id, { text: 'extract_article' }, printResponse);
}
});

// When the extension is installed or upgraded ...
chrome.runtime.onInstalled.addListener(function() {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
// That fires when a page's URL contains a 'feedly.com' ...
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlContains: 'feedly.com' },
})
],
// And shows the extension's page action.
actions: [ new chrome.declarativeContent.ShowPageAction() ]
}
]);
});
});

console.log('\'Allo \'Allo! Event Page for Page Action');
console.log('FullyFeedly: extension started');
97 changes: 97 additions & 0 deletions app/scripts/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use strict';

/**
* Performs an XMLHttpRequest to boilerpipe to get the content of the artile.
*
* @param callback Function If the response from fetching url has a
* HTTP status of 200, this function is called with a JSON decoded
* response. Otherwise, this function is called with null.
*/
function fetchPageContent(callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
callback(data);
} else {
callback(null);
}
}
};

// Search the link of the article that is currently opened
var linkElement = document.querySelector('.websiteCallForAction');
if (linkElement === null) {
console.log('There is something wrong: no link element found');
return;
}

// Get the link and convert it for usage as parameter in the GET request
var pageUrl = linkElement.getAttribute('href');
var encodedPageUrl = encodeURIComponent(pageUrl);

// Prepare the request to Boilerpipe
var url = 'http://boilerpipe-web.appspot.com/extract?url=' +
encodedPageUrl +
'&extractor=ArticleExtractor&output=json&extractImages=';
xhr.open('GET', url, true);
xhr.send();
}

/**
* Process the content of the article and add it to the page
*
* @param data Object JSON decoded response. Null if the request failed.
*/
function onArticleExtracted(data) {

// Check if the request failed
if (data === null) {
console.log('Failed to load the content of the page');
return;
}

// Check if the API failed to extract the text
if (data.status === null || data.status !== 'success') {
console.log('API failed to extract the content');
return;
}

// Get the content of the article
var articleContent = data.response.content;

// Search the element of the page that will containt the text
var contentElement = document.querySelector('.content');
if (contentElement === null) {
console.log('There is something wrong: no content element found');
return;
}

// If there is an image we want to keep it
var articleImage = contentElement.querySelector('img');
if (articleImage !== null) {
articleImage = articleImage.cloneNode();
}

// Replace the preview of the article with the full text
contentElement.innerText = articleContent;

// Put the image back at the beginning of the article
if (articleImage !== null) {
contentElement.insertBefore(articleImage, contentElement.firstChild);
}

}

/* Listen for requests */
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
// If the received message has the expected format...
if (msg.text && (msg.text === 'extract_article')) {
// Perform the specified operation
fetchPageContent(onArticleExtracted);
sendResponse('Got it!');
}
});


Binary file added resources/icon-128.pxm
Binary file not shown.
Binary file added resources/icon-16.pxm
Binary file not shown.
Binary file added resources/icon-19.pxm
Binary file not shown.
Binary file added resources/icon-38.pxm
Binary file not shown.

0 comments on commit d6abbd1

Please sign in to comment.