Skip to content

Commit

Permalink
README/UI/docs, publish for Chrome, remove older reader mode workaround
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasGollenstede committed Apr 21, 2019
1 parent 2c39ef8 commit e4e571f
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 112 deletions.
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,47 @@
# ePub Creator -- create ePubs from web pages and `overdrive.com`s online reader
# ePub Creator -- offline e-books in a single click

<!-- This section can be copied as the AMO listing. -->
<a href="https://addons.mozilla.org/firefox/addon/epub/"><img src="./resources/get-firefox-ext-172x60.png" width="86" height="30"></a>
<a href="https://addons.mozilla.org/firefox/addon/epub/"><img src="./resources/get-chrome-ext-206x58.png" width="103" height="29"></a>

<!-- START:listing (This section can be copied as the AMO listing. The weired spacing is required.) -->

ePub creator allows you to save web pages opened in the browser as offline ePub e-books.
It currently supports:<ul>
<li> books opened in the online reader of the library service <a href="https://www.overdrive.com/">overdrive.com</a> </li>
<li> any web page that can be opened in Firefox's Reader Mode </li>
<li> any web page that can be opened in Firefox's Reader Mode, which should work for most text-based websites </li>
<li> books opened in the online reader of the library service <a href="https://www.overdrive.com/">overdrive.com</a>, which cooperates with many local libraries worldwide </li>
</ul>

<b>Instructions:</b>
<b>How to</b> create/save books:</b>
<ol>
<li> open the page / book you want to save (on overdrive, go to "Loans" and choose "Read now in browser") </li>
<li> open the web page or book you want to save <ul>
<li> on overdrive, go to "Loans" and choose "Read now in browser" </li>
</ul></li>
<li> click the extensions icon (blue book with green arrow, should be at the top right of the browser, see screenshot) </li>
<li> wait while the animation on the icon is spinning (this can take a while in the e-book contains many pictures etc.) </li>
<li> wait while the animation on the icon is spinning <ul>
<li> this can take a while if the e-book contains many pictures etc. </li>
<li> for Reader Mode pages, it will prompt for the books author </li>
</ul></li>
<li> save or open the e-book when prompted </li>
</ol>

Whether saving content this way is <b>legal or not</b> depends on the content and your <b>local legislation</b>. Checking this is <b>your own responsibility</b>. Just because you can do it doesn't mean you should.
Whether saving content with this extension is <b>legal or not</b> depends on the content and your <b>local legislation</b>. Checking that is <b>your own responsibility</b>. Just because you can do it doesn't mean you should.


What you get &amp; <b>Troubleshooting:</b>
<ul>
<li> For general web pages, Mozilla's <code>Readability.js</code> is used to extract the content. Since that is the same software component used by Firefox to generate the Reader view, the result should generally be the same as well. All resources (e.g. images) that show up there should also be included in the ePub book. If parts of the website are missing in the book, please check whether they show up in the reader mode. If not, there is little I can change about that. </li>
<li> Books from <a href="https://www.overdrive.com/">overdrive.com</a> are not simply downloaded, but the content is parsed from the open book. The ToC is rewritten, most of the formatting is stripped and everything gets repacked. While images are generally still included, their sizing might be off on some readers, rendering this quite useless for comics and the like. </li>
<li> If you have a problem that is not explained by the limitations above, please check for and/or open an <a href="https://github.com/NiklasGollenstede/epub-creator/issues">Issue on GutHub</a>. </li>
</ul>


<b>Permissions used</b>:<ul>
<li> <b>Display notifications</b>: Only as direct consequence of clicks on the icon or to report errors </li>
<li> <b>Access your data for all websites</b>: Download page content <b>if you choose so</b> </li>
<li> <b>Access recently closed tabs</b>: Remove own popups from the recently closed windows list </li>
</ul>

<!-- END:listing -->

## Development builds -- ![](https://ci.appveyor.com/api/projects/status/github/NiklasGollenstede/epub-creator?svg=true)

Expand Down Expand Up @@ -52,7 +70,7 @@ The `.zip` file is ready to be uploaded on AMO, and the `build/` directory or th

To test the extension in a fresh Firefox profile, use the `{run:1}` or `{run:{bin:'path/to firefox/binary'}}` option.

To build for chrome (which e.g. doesn't support `.svg` icons), add the `{chrome:1}` option.
To build for Chrome (which e.g. doesn't support `.svg` icons), add the `{chrome:1}` option.


## AMO code review notes
Expand Down
19 changes: 13 additions & 6 deletions background/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
(function(global) { 'use strict'; define(({ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
'node_modules/web-ext-utils/browser/': { BrowserAction, manifest, },
'node_modules/web-ext-utils/browser/': { BrowserAction, Tabs, manifest, },
'node_modules/web-ext-utils/loader/': { runInFrame, },
'node_modules/web-ext-utils/update/': updated,
'node_modules/web-ext-utils/utils/notify': notify,
Expand All @@ -12,16 +12,23 @@ async function onClicked(tab) { return spinner.run(async () => {
let collector, name = null;

if (tab.isInReaderMode) {
name = (await (await require.async('./reader-mode'))(tab.url));
} else if (/^https:\/\/[^/]*read\.overdrive\.com/.test(tab.url)) {
notify({
title: `Exit reader mode?`, icon: 'default', // 'prompt',
message: `${manifest.name} can only save this page after closing the reader mode.\nClick here if you want leave reader mode.\nThen try again.`,
}).then(async clicked =>
clicked && (await Tabs.get(tab.id)).isInReaderMode && Tabs.toggleReaderMode(tab.id)
); return;
} else if ((/^https:[/][/][^/]*read[.]overdrive[.]com/).test(tab.url)) {
collector = 'overdrive';
} else if (tab.isArticle) {
} else if (tab.isArticle || !('isArticle' in tab)) {
collector = 'readability';
} else {
notify({
title: `Force reader mode?`, icon: 'warn',
message: `It seems ${manifest.name} doesn't support this page.\nClick here if you want to TRY to force a book from reader mode.`,
}).then(async clicked => clicked && onClicked({ isArticle: true, id: tab.id, })); return;
}).then(async clicked =>
clicked && onClicked({ isArticle: true, id: tab.id, })
); return;
}

collector && (name = (await runInFrame(tab.id, 0,
Expand All @@ -31,7 +38,7 @@ async function onClicked(tab) { return spinner.run(async () => {
if (name) { console.info(`Saved book "${name}"`); }
else { console.info(`Saving as book was aborted`); }

}).catch(notify.error); }
}).catch(notify.error.bind(null, 'Failed to save as ePub')); }

const spinner = {
active: 0, strings: String.raw`\ | / –`.split(' '),
Expand Down
83 changes: 0 additions & 83 deletions background/reader-mode.js

This file was deleted.

7 changes: 5 additions & 2 deletions build-config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/*eslint strict: ["error", "global"], no-implicit-globals: "off"*/ 'use strict'; /* globals module, */ // license: MPL-2.0
module.exports = function({ options, /*packageJson,*/ manifestJson, files, }) {
module.exports = function({ options, packageJson, manifestJson, files, }) {

manifestJson.description = `Create offline e-books from web pages and 'overdrive.com' with a single click on the icon.`;
manifestJson.homepage_url = packageJson.homepage;

manifestJson.permissions.push(
'notifications',
'sessions', // to remove own closed popups
'activeTab',
'<all_urls>', // for fetch in background/reader-mode.js
'<all_urls>', // required to fetch DORS stuff
);

manifestJson.browser_action = {
Expand Down
2 changes: 1 addition & 1 deletion common/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
const model = {
setNavProperty: {
title: `Set 'nav' property`,
description: `Standard compliant when set, but disables the navigation in Sumatra PDF`,
description: `Standard compliant when set, but disables the navigation in Sumatra PDF.`,
default: false,
input: { type: 'boolean', },
},
Expand Down
6 changes: 3 additions & 3 deletions content/collect/about-reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

const doc = document.querySelector('.container').cloneNode(true);

const resources = (await Promise.all(Array.map(doc.querySelectorAll('img'), async img => {
const resources = (await Promise.all(Array.from(doc.querySelectorAll('img'), async img => {
const { src, } = img, name = img.src = (await sha1(src)) +'/'+ src.match(/[^/]*[/]?(?:[?]|#|$)/)[0];
return { src, name, };
})));
Expand All @@ -19,8 +19,8 @@ const author = global.prompt('Please enter/confirm the authors name', (
).textContent.replace(/\s+/g, ' ') || '<unknown>');
if (author == null) { return null; }

Array.forEach(doc.querySelectorAll('style, link, menu'), element => element.remove());
Array.forEach(doc.querySelectorAll('*'), element => {
doc.querySelectorAll('style, link, menu').forEach(element => element.remove());
doc.querySelectorAll('*').forEach(element => {
for (let i = element.attributes.length; i-- > 0;) {
const attr = element.attributes[i];
if ([ 'class', 'src', 'href', 'title', 'alt', ].includes(attr.name)) { continue; }
Expand Down
4 changes: 2 additions & 2 deletions content/collect/overdrive.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const chapters = (await Promise.all(bData.spine.map(async ({
.italic { font-style: italic; }
.underline { text-decoration: underline; }
.bold { font-weight: bold; }
` );
`);
options.styles && (css += Array.from(styles, ([ style, index, ]) => `\t\t.inline-${index} { ${style} }\n`).join(''));

// html clean-up
Expand Down Expand Up @@ -91,7 +91,7 @@ const chapters = (await Promise.all(bData.spine.map(async ({
return ({
name: name && decodeURI(name) || 'unnamed'+ index +'.html',
title,
content: toXML(document).replace(/^.*$/m, `<?xml version="1.0" encoding="UTF-8"?>`),
content: toXML(document).replace(/^.*?>/, `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n`),
mimeType: 'xhtml', // toXML produces xhtml
linear,
});
Expand Down
6 changes: 4 additions & 2 deletions content/collect/readability.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
'shim!node_modules/readability/Readability:Readability': Readability,
aboutReader,
}) => async function collect({ document: srcDoc = global.document.cloneNode(true), url = srcDoc.URL, } = { }) {

/**
* Can't access pages in reader mode any more, so this emulates the reader mode
* Collects the contents of any website that can be opened in the `about:reader` view.
* Since extensions can't access pages in reader mode any more, this emulates the reader mode
* in the original content page and then proceeds as if it was loaded in `about:reader`.
* (This workaround is kept for now to be able to switch back to the reader view if it ever becomes accessible again.)
* @return {object} Options that can be passed as argument to the EPub constructor.
*/

const parsed = new Readability(srcDoc, { }).parse();
Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "epub",
"version": "0.5.4",
"version": "0.5.5",
"title": "ePub Creator",
"description": "ePub Creator is a WebExtension that creates ePub e-books from web pages and 'overdrive.com's online reader.",
"author": "Niklas Gollenstede",
Expand All @@ -9,6 +9,8 @@
"type": "git",
"url": "https://github.com/NiklasGollenstede/epub-creator"
},
"homepage": "https://github.com/NiklasGollenstede/epub-creator#readme",
"keywords": [ "book", "e-book", "ePub", "website", "article", "save", "offline", "one click", "overdrive.com", "reader mode" ],
"contributions": [ {
"what": { "name": "Readability.js", "url": "https://github.com/mozilla/readability" },
"who": [ "Mozilla", "Arc90" ],
Expand All @@ -26,10 +28,10 @@
"es6lib": "0.0.3",
"jszip": "github:Stuk/jszip#v3.1.5",
"multiport": "0.2.3",
"pbq": "0.3.5",
"readability": "github:mozilla/readability#d8c8370",
"pbq": "0.4.1",
"readability": "github:mozilla/readability#26379fe",
"web-ext-build": "0.0.10",
"web-ext-utils": "0.1.8"
"web-ext-utils": "0.1.11"
},
"devDependencies": {
"eslintrc": "github:NiklasGollenstede/eslintrc#5837452",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/get-chrome-ext-206x58.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 added resources/get-firefox-ext-172x60.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e4e571f

Please sign in to comment.