aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRahiel Kasim <rahielkasim@gmail.com>2018-04-16 12:33:12 +0200
committerRahiel Kasim <rahielkasim@gmail.com>2018-04-16 12:33:12 +0200
commitc0014258ebb5a4d00b6c58869deb57a0efbf9e7f (patch)
treef2b3a6106228ba96c0751eb6789b7886aaf2b744
parent666fd7f4723a0dbfced60f41aeb21aa7bf7fb66d (diff)
popup for browser action, multiple bookmark archive services, refactoring
-rw-r--r--LICENSE.txt2
-rwxr-xr-xbuild.bash2
-rw-r--r--src/archiveror.js159
-rw-r--r--src/manifest.json14
-rw-r--r--src/options.html62
-rw-r--r--src/options.js53
-rw-r--r--src/popup.css30
-rw-r--r--src/popup.html27
-rw-r--r--src/popup.js60
-rw-r--r--src/utils.js25
-rw-r--r--webpack.config.js3
11 files changed, 275 insertions, 162 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
index 49db015..2986df8 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2017 Rahiel Kasim
+Copyright (c) 2015-2018 Rahiel Kasim
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
diff --git a/build.bash b/build.bash
index 9666ece..364bd30 100755
--- a/build.bash
+++ b/build.bash
@@ -19,4 +19,4 @@ if [[ $BROWSER = 'chromium' ]]; then
mv mani.json manifest.json
fi
-zip archiveror.zip *.js *.html *.png manifest.json LICENSE.txt
+zip archiveror.zip *.js *.html *.css *.png manifest.json LICENSE.txt
diff --git a/src/archiveror.js b/src/archiveror.js
index 18a49a1..a388de5 100644
--- a/src/archiveror.js
+++ b/src/archiveror.js
@@ -1,4 +1,4 @@
-import { getArchivingURL, isLocal, services, hasPageCapture } from "./utils.js";
+import { defaults, getArchivingURL, isLocal, services, hasPageCapture } from "./utils.js";
function archive_is(url) {
@@ -10,25 +10,24 @@ function archive_is(url) {
request.onreadystatechange = function () {
if (request.readyState === 4) {
let link = request.response.match(/(https?:\/\/archive.is\/\w+)/)[0];
+ // TODO: upgrade link to https
postArchive(url, link);
}
};
request.send(params);
-}
-function postArchive(url, link) {
- let data = {};
- data[url] = link;
- chrome.storage.local.set(data, function () {
- showArchive(url);
- });
+ function postArchive(url, link) {
+ chrome.storage.local.set({[url]: link}, function () {
+ showArchive(url);
+ });
+ }
}
-// archive url online at services (a list of strings)
-function archivePage(url, services) {
+function archiveOnline(url, services) {
+ // archive url online at services (a list of strings)
if (isLocal(url)) return; // don't archive internal pages, "file://", "chrome://", etc.
let tabId, link;
- chrome.storage.local.get({archiveServices: ["archive.is"], email: ""}, function (items) {
+ chrome.storage.local.get({archiveServices: defaults.archiveServices, email: defaults.email}, function (items) {
if (services === undefined) {
services = items.archiveServices;
}
@@ -59,7 +58,19 @@ function archivePage(url, services) {
}
}
+// archive requests from popup
+chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
+ if (message.label === "archiveOnline") {
+ archiveOnline(message.url, message.services);
+ } else if (message.label === "saveLocal") {
+ chrome.tabs.get(message.tabId, function (tab) {
+ saveLocal(tab, false);
+ });
+ }
+});
+
function writeClipboard(text) {
+ // write text to clipboard
let textarea = document.createElement("textarea");
textarea.textContent = text;
document.body.appendChild(textarea);
@@ -72,31 +83,38 @@ function writeClipboard(text) {
}
function showArchive(url, bookmark) {
- // Notify user if we have an archive of the current page
- chrome.storage.local.get({archiveMode: "online", archiveBookmarks: true}, function (items) {
- if (items.archiveMode === "local") {
- showBadge("_" + url, items.archiveBookmarks);
- } else {
- showBadge(url, items.archiveBookmarks);
- }
- });
+ // Notify user if we have an archive of the current page, otherwise archive if needed
+ let keys = {
+ [url]: false,
+ ["_" + url]: false,
+ archiveBookmarks: defaults.archiveBookmarks,
+ bookmarkServices: defaults.bookmarkServices
+ };
+ chrome.storage.local.get(keys, showBadge);
- function showBadge(url, archiveBookmarks) {
- chrome.storage.local.get(url, function (data) {
- if (data[url]) {
- let taburl = normalURL(url).split("#")[0];
- chrome.tabs.query({"url": taburl}, function (tabs) {
- changeBadge(tabs, buttonTitle.present, "!", "#FFB90F");
- });
- } else if (archiveBookmarks === true) {
- archive(normalURL(url), true, undefined, bookmark);
+ function showBadge(items) {
+ let taburl = url.split("#")[0];
+ chrome.tabs.query({"url": taburl}, function (tabs) {
+ let save = (items.archiveBookmarks === true);
+ let title = buttonTitle.default + " (bookmark archived)";
+
+ if (items[url] !== false) {
+ changeBadge(tabs, title, "!", "#FFB90F");
+ } else {
+ if (save && items.bookmarkServices.includes("archive.is")) archive_is(url);
}
- });
- }
- function normalURL(url) {
- if (url[0] === "_") return url.slice(1);
- else return url;
+ if (items["_" + url] !== false) {
+ changeBadge(tabs, title, "!", "#FFB90F");
+ } else {
+ if (save && items.bookmarkServices.includes("mhtml")) {
+ downloadBlock.push(tabs[0].id);
+ getPath(bookmark, function (path) {
+ saveLocal(tabs[0], save, path);
+ });
+ }
+ }
+ });
}
}
@@ -109,59 +127,11 @@ function changeBadge(tabs, title, badgeText, badgeColor) {
}
}
-const buttonTitle = {default: "Archive Page", present: "Go to archived page"};
-
-function archiveClick(tab) {
- // When user clicks on button
- chrome.browserAction.getTitle({tabId: tab.id}, function (text) {
- if (text === buttonTitle.present) {
- chrome.storage.local.get({archiveMode: "online"}, function (items) {
- if (items.archiveMode === "local") {
- chrome.storage.local.get("_" + tab.url, function (data) {
- let url = data["_" + tab.url].filename;
- chrome.tabs.create({"url": "file://" + url});
- });
- } else {
- chrome.storage.local.get(tab.url, function (key) {
- chrome.tabs.create({"url": key[tab.url]});
- });
- }
- });
- } else if (text === buttonTitle.default) {
- archive(tab.url, false, tab);
- }
- });
-}
-chrome.browserAction.onClicked.addListener(archiveClick);
-
-function archive(url, save, tab, bookmark) {
- // tab and bookmark are optional
- chrome.storage.local.get({archiveMode: "online"}, userAction);
-
- function userAction(items) {
- if (items.archiveMode === "online") {
- if (save === true) archive_is(url);
- else archivePage(url);
- } else {
- if (typeof tab === "undefined") { // for bookmark visit / creation
- // tabs.query doesn't match fragment identifiers
- url = url.split("#")[0];
- chrome.tabs.query({"url": url}, function (tabs) {
- downloadBlock.push(tabs[0].id);
- getPath(bookmark, function (path) {
- saveLocal(tabs[0], save, path);
- });
- });
- } else {
- saveLocal(tab, save); // will never need bookmark
- }
- }
- }
-}
+const buttonTitle = {default: "Archiveror"};
function silentDownload(url, filename, path, callback) {
// silently download to archiveDir
- chrome.storage.local.get({archiveDir: "Archiveror"}, function (items) {
+ chrome.storage.local.get({archiveDir: defaults.archiveDir}, function (items) {
filename = items.archiveDir + path + filename;
chrome.downloads.download({
url: url, filename: filename, saveAs: false, conflictAction: "overwrite"}, callback);
@@ -257,7 +227,7 @@ function getTimestamp() {
chrome.commands.onCommand.addListener(function (command) {
let action;
if (command === "archive-page") {
- action = function (tabs) { archivePage(tabs[0].url); };
+ action = function (tabs) { archiveOnline(tabs[0].url); };
} else if (command === "save-local") {
action = function (tabs) { saveLocal(tabs[0], false); };
}
@@ -288,16 +258,14 @@ chrome.contextMenus.onClicked.addListener(function (info, tab) {
if (info.menuItemId === "MHTML") {
saveLocal(tab, false);
} else {
- archivePage(info.pageUrl, [info.menuItemId]);
+ archiveOnline(info.pageUrl, [info.menuItemId]);
}
});
function newBookmark(id, bookmark) {
- chrome.storage.local.get({archiveBookmarks: true}, function (items) {
- if (bookmark.hasOwnProperty("url") && items.archiveBookmarks === true) {
- archive(bookmark.url, true, undefined, bookmark);
- }
- });
+ if (bookmark.hasOwnProperty("url")) {
+ showArchive(bookmark.url, bookmark);
+ }
}
chrome.bookmarks.onCreated.addListener(newBookmark);
@@ -326,7 +294,6 @@ function bookmarkVisit(tabId, changeInfo, tab) {
if (downloadBlock.indexOf(tabId) > -1) return;
chrome.bookmarks.search({url: tab.url}, function (bookmarks) {
if (bookmarks.length > 0 && bookmarks[0].url === tab.url) {
- // bookmarks[0] propagates to archive function
showArchive(bookmarks[0].url, bookmarks[0]);
}
});
@@ -407,3 +374,13 @@ function removeBookmark(id, removeInfo) {
}
}
chrome.bookmarks.onRemoved.addListener(removeBookmark);
+
+// Remove deprecated "archiveMode" setting. TODO: remove this
+chrome.runtime.onInstalled.addListener(function (details) {
+ let key = "archiveMode";
+ chrome.storage.local.get(key, function (items) {
+ if (items[key]) {
+ chrome.storage.local.remove(key);
+ }
+ });
+});
diff --git a/src/manifest.json b/src/manifest.json
index 7cdba92..b3bcc39 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -17,15 +17,16 @@
},
"permissions": [
- "tabs",
+ "<all_urls>",
"bookmarks",
- "storage",
+ "clipboardWrite",
+ "contextMenus",
"downloads",
"downloads.shelf",
"pageCapture",
- "<all_urls>",
- "clipboardWrite",
- "contextMenus"
+ "storage",
+ "tabs",
+ "unlimitedStorage"
],
"background": {
@@ -38,7 +39,8 @@
"19": "icon-19.png",
"38": "icon-38.png"
},
- "default_title": "Archive Page"
+ "default_title": "Archiveror",
+ "default_popup": "popup.html"
},
"options_ui": {
diff --git a/src/options.html b/src/options.html
index cd704d3..c6183bb 100644
--- a/src/options.html
+++ b/src/options.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
<head>
+ <meta charset="utf-8">
<title>Archiveror Options</title>
<style type="text/css">
body {padding: 10px; line-height: 1.6; font-size: 14px}
@@ -9,7 +10,7 @@
</head>
<body>
<h3>Archiving Service</h3>
- <p>The online archiving service(s) to use for manual archiving.</p>
+ <p>The archiving service(s) to use for manual archiving.</p>
<label for="archive.is">
<input type="checkbox" name="service" id="archive.is" value="archive.is">
<a href="https://archive.is/">archive.is</a>
@@ -29,16 +30,42 @@
<input type="checkbox" name="service" id="webcitation.org" value="webcitation.org">
<a href="http://webcitation.org/">webcitation.org</a> (requires email, no HTTPS)
</label>
-
- <div id="archivingMode">
- <h3>Archiving mode</h3>
- <label for="online">
- <input type="radio" name="mode" id="online" value="online">Online
+ <br>
+ <div class="mhtml">
+ <label for="mhtml">
+ <input type="checkbox" name="service" id="mhtml" value="mhtml">
+ MHTML
</label>
- <br>
- <label for="local">
- <input type="radio" name="mode" id="local" value="local">Local (MHTML)
+ </div>
+
+ <div id="email_option">
+ <h3>Email Address</h3>
+ The email address used for archiving on webcitation.org. You will receive a link to the archive by email.
+ <table>
+ <tr>
+ <td><label for="email">Email:</label></td>
+ <td><input type="text" id="email"></td>
+ </tr>
+ </table>
+ </div>
+
+ <h3>Bookmarks</h3>
+ <label for="bookmarks">
+ <input type="checkbox" id="bookmarks">Automatically archive bookmarks
+ </label>
+ <div id="bookmark_options">
+ <p>Select which archives to make for bookmarks:</p>
+
+ <label for="bookmark-archive.is">
+ <input type="checkbox" name="bookmarkService" id="bookmark-archive.is" value="archive.is">
+ <a href="https://archive.is/">archive.is</a>
</label>
+ <div class="mhtml">
+ <label for="bookmark-mhtml">
+ <input type="checkbox" name="bookmarkService" id="bookmark-mhtml" value="mhtml">
+ MHTML
+ </label>
+ </div>
</div>
<div id="local_options" style="display:none">
@@ -54,23 +81,6 @@
(<a href="https://support.google.com/chrome/answer/95574">instructions</a>)
</div>
- <div id="email_option">
- <h3>Email Address</h3>
- The email address used for archiving on webcitation.org. You will receive a link to the archive by email.
- <table>
- <tr>
- <td><label for="email">Email:</label></td>
- <td><input type="text" id="email"></td>
- </tr>
- </table>
- </div>
-
- <div style="margin-bottom: 10px">
- <h3>Bookmarks</h3>
- <label for="bookmarks">
- <input type="checkbox" id="bookmarks">Automatically archive bookmarks
- </label>
- </div>
<script src="options.js"></script>
</body>
diff --git a/src/options.js b/src/options.js
index a7f837c..61e02d7 100644
--- a/src/options.js
+++ b/src/options.js
@@ -1,11 +1,10 @@
-import { hasPageCapture } from "./utils.js";
+import { defaults, hasPageCapture } from "./utils.js";
function saveOptions() {
function getOptions(name) {
- // get the selected options by name
- let checkboxes = document.getElementsByName(name);
+ let checkboxes = document.getElementsByName(name); // get the selected options by name
let options = [];
for (let c of checkboxes) {
if (c.checked === true) {
@@ -15,30 +14,29 @@ function saveOptions() {
return options;
}
- let mode = getOptions("mode")[0];
let services = getOptions("service");
+ let bookmarkServices = getOptions("bookmarkService");
- let dir = document.getElementById("dir").value;
- // TODO: check dir for forbidden characters
+ let dir = document.getElementById("dir").value; // TODO: check dir for forbidden characters
let email = document.getElementById("email").value;
let bookmarks = document.getElementById("bookmarks").checked;
chrome.storage.local.set({
archiveBookmarks: bookmarks,
archiveDir: dir,
- archiveMode: mode,
archiveServices: services,
+ bookmarkServices: bookmarkServices,
email: email,
});
}
function restoreOptions() {
- chrome.storage.local.get({ // below are the default values
- archiveBookmarks: true,
- archiveDir: "Archiveror",
- archiveMode: "online",
- archiveServices: ["archive.is"],
- email: "",
+ chrome.storage.local.get({
+ archiveBookmarks: defaults.archiveBookmarks,
+ archiveDir: defaults.archiveDir,
+ archiveServices: defaults.archiveServices,
+ bookmarkServices: defaults.bookmarkServices,
+ email: defaults.email,
}, setOptions);
function setOptions(items) {
@@ -51,18 +49,15 @@ function restoreOptions() {
for (let s of items.archiveServices) {
document.getElementById(s).checked = true;
}
-
- if (items.archiveMode === "online") {
- document.getElementById("online").checked = true;
- } else {
- document.getElementById("local").checked = true;
- document.getElementById("local_options").style.display = "block";
+ for (let s of items.bookmarkServices) {
+ document.getElementById("bookmark-" + s).checked = true;
}
+
+ showLocal();
}
}
document.addEventListener("DOMContentLoaded", restoreOptions);
-document.getElementById("local").addEventListener("click", showLocal);
-document.getElementById("online").addEventListener("click", showLocal);
+document.getElementById("bookmark-mhtml").addEventListener("click", showLocal);
let inputs = document.querySelectorAll(`input[type="checkbox"], input[type="radio"]`);
for (let input of inputs) {
@@ -74,15 +69,19 @@ for (let input of textInputs) {
}
function showLocal() {
- let local = document.getElementById("local").checked;
+ // show/hide options for local archiving
+ if (!hasPageCapture) {
+ let options = document.getElementsByClassName("mhtml");
+ for (let opt of options) {
+ opt.style.display = "none";
+ }
+ }
+
+ let local = document.getElementById("bookmark-mhtml").checked;
if (local === true) {
document.getElementById("local_options").style.display = "block";
} else {
document.getElementById("local_options").style.display = "none";
}
-}
-
-if (!hasPageCapture) {
- let div = document.getElementById("archivingMode");
- div.style.display = "none";
+ // TODO: show/hide bookmark_options
}
diff --git a/src/popup.css b/src/popup.css
new file mode 100644
index 0000000..f6f01c3
--- /dev/null
+++ b/src/popup.css
@@ -0,0 +1,30 @@
+button {
+ color: #fff;
+ background-color: #337ab7;
+ border: 1px solid #2e6da4;
+ border-radius: 4px;
+ padding: 6px 12px;
+ margin: 5px 3px;
+ width: 100%;
+ text-align: center;
+}
+
+button:hover {
+ background-color: #286090;
+ border-color: #204d74;
+}
+
+ul {
+ padding-left: 15px;
+}
+
+a {
+ color: #1a0dab;
+ text-decoration: none;
+}
+a:hover { text-decoration: underline; }
+a:visited { color: #609; }
+
+#bookmarkSection {
+ display: none;
+}
diff --git a/src/popup.html b/src/popup.html
new file mode 100644
index 0000000..6da76b8
--- /dev/null
+++ b/src/popup.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="popup.css">
+ <title>Archiveror</title>
+ </head>
+ <body>
+ <h3>Archive Online</h3>
+ <button type="button" id="archive.is">archive.is</button>
+ <button type="button" id="archive.org">archive.org</button>
+ <button type="button" id="perma.cc">perma.cc</button>
+ <button type="button" id="webcitation.org">webcitation.org</button>
+
+ <h3>Archive Locally</h3>
+ <button type="button" id="mhtml">MHTML</button>
+
+ <div id="bookmarkSection">
+ <h3>Bookmark</h3>
+ Archives of this bookmark:
+ <ul id="archiveList">
+ </ul>
+ </div>
+
+ <script src="popup.js"></script>
+ </body>
+</html>
diff --git a/src/popup.js b/src/popup.js
new file mode 100644
index 0000000..b80e237
--- /dev/null
+++ b/src/popup.js
@@ -0,0 +1,60 @@
+function click(services) {
+
+ function requestArchive() {
+ chrome.tabs.query({active: true, lastFocusedWindow: true}, function (tabs) {
+ let url = tabs[0].url;
+ chrome.runtime.sendMessage({
+ label: "archiveOnline",
+ services: services,
+ url: url,
+ });
+ });
+ }
+
+ return requestArchive;
+}
+
+function requestMHTML() {
+ chrome.tabs.query({active: true, lastFocusedWindow: true}, function (tabs) {
+ let tab = tabs[0];
+ chrome.runtime.sendMessage({
+ label: "saveLocal",
+ tabId: tab.id,
+ });
+ });
+}
+
+document.getElementById("archive.is").onclick = click(["archive.is"]);
+document.getElementById("archive.org").onclick = click(["archive.org"]);
+document.getElementById("perma.cc").onclick = click(["perma.cc"]);
+document.getElementById("webcitation.org").onclick = click(["webcitation.org"]);
+
+document.getElementById("mhtml").onclick = requestMHTML;
+
+function showBookmarkArchives() {
+ chrome.tabs.query({active: true, lastFocusedWindow: true}, function (tabs) {
+ let url = tabs[0].url;
+ chrome.storage.local.get([url, "_" + url], function (items) {
+ let showBookmarkSection = false;
+ if (items[url]) {
+ addArchiveLink(items[url]);
+ }
+ if (items["_" + url]) {
+ addArchiveLink("file://" + items["_" + url].filename);
+ }
+
+ if (showBookmarkSection === true) {
+ document.getElementById("bookmarkSection").style.display = "block";
+ }
+
+ function addArchiveLink(url) {
+ let e = document.createElement("li");
+ e.innerHTML = `<a href="${url}">${url}</a>`;
+ e.onclick = function () { chrome.tabs.create({url: url}); };
+ document.getElementById("archiveList").appendChild(e);
+ showBookmarkSection = true;
+ }
+ });
+ });
+}
+showBookmarkArchives();
diff --git a/src/utils.js b/src/utils.js
index b8e081e..21eb177 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,8 +1,22 @@
-export const services = ["archive.is", "archive.org", "perma.cc", "webcitation.org"];
+export const services = ["archive.is", "archive.org", "perma.cc", "webcitation.org"]; // note: doesn't include "mhtml"
-const blacklist = ["file://", "about:", "chrome://", "http://127.0.0.1", "http://localhost"];
+export const defaults = {
+ archiveBookmarks: true,
+ archiveDir: "Archiveror",
+ archiveServices: ["archive.is"],
+ bookmarkServices: ["archive.is"],
+ email: "",
+};
+
+export let hasPageCapture;
+if (chrome.hasOwnProperty("pageCapture")) {
+ hasPageCapture = true;
+} else {
+ hasPageCapture = false;
+}
export function isLocal(url) {
+ const blacklist = ["file://", "about:", "chrome://", "http://127.0.0.1", "http://localhost"];
for (let b of blacklist) {
if (url.startsWith(b)) return true;
}
@@ -22,10 +36,3 @@ export function getArchivingURL(page, service, email) {
}
return url;
}
-
-export let hasPageCapture;
-if (chrome.hasOwnProperty("pageCapture")) {
- hasPageCapture = true;
-} else {
- hasPageCapture = false;
-}
diff --git a/webpack.config.js b/webpack.config.js
index bcbdde3..ebebfe3 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -4,7 +4,8 @@ const webpack = require("webpack");
module.exports = {
entry: {
"dist/archiveror": "./src/archiveror.js",
- "dist/options": "./src/options.js"
+ "dist/options": "./src/options.js",
+ "dist/popup": "./src/popup.js",
},
output: {
path: __dirname + "/",