Skip to content

Commit

Permalink
feat/fix(): UI rebuild => everything is a bookmark context entry
Browse files Browse the repository at this point in the history
  • Loading branch information
igorlogius committed Mar 8, 2024
1 parent db8d769 commit f1a3286
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 245 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ Import or export a branch of the bookmark tree as a JSON or HTML file

<b>Usage:</b>
<ol>
<li>click toolbar icon</li>
<li>the preference page will open</li>
<li>on the preference page you can use the Import or Export section</li>
<li>click on a bookmark folder</li>
<li>in the "Bookmark Branch Porter" context menu select the export/import options</li>
<li>to remove/hide the context, you can disable the addon</li>
</ol>

<b>Notes:</b>
Expand Down
9 changes: 6 additions & 3 deletions about.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

<b>Usage:</b>
<ol>
<li>click toolbar icon</li>
<li>the preference page will open</li>
<li>on the preference page you can use the Import or Export section</li>
<li>click on a bookmark folder</li>
<li>
in the "Bookmark Branch Porter" context menu select the export/import
options
</li>
<li>to remove/hide the context, you can disable the addon</li>
</ol>
159 changes: 157 additions & 2 deletions background.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,160 @@
/* global browser */

browser.browserAction.onClicked.addListener(() => {
browser.runtime.openOptionsPage();
function htmlEncode(input) {
const textArea = document.createElement("textarea");
textArea.innerText = input;
return textArea.innerHTML.split("<br>").join("\n");
}

async function exportJSON(bookmarkId) {
if (typeof bookmarkId !== "string") {
bookmarkId = "root________";
}
const data = (await browser.bookmarks.getSubTree(bookmarkId))[0];

const content = JSON.stringify(data, null, 4);
let dl = document.createElement("a");
let textFileAsBlob = new Blob([content], { type: "text/plain" });
dl.setAttribute("href", window.URL.createObjectURL(textFileAsBlob));
dl.setAttribute(
"download",
"export " + (bookmarkId === "root________" ? "all" : data.title) + ".json"
);
dl.setAttribute("visibility", "hidden");
dl.setAttribute("display", "none");
document.body.appendChild(dl);
dl.addEventListener("click", () => {
document.body.removeChild(dl);
});
dl.click();
}

function rec2HtmlStr(bmTreeNode, level = 1) {
let out = "";
"\t".repeat(level);
let tmp = "";
const title =
typeof bmTreeNode.title === "string" ? htmlEncode(bmTreeNode.title) : "";
if (typeof bmTreeNode.url === "string") {
out =
out +
"\t".repeat(level) +
'<DT><A HREF="' +
htmlEncode(bmTreeNode.url) +
'">' +
title +
"</A>" +
"\n";
} else if (Array.isArray(bmTreeNode.children)) {
tmp = "\t".repeat(level) + "<DT><H3>" + htmlEncode(title) + "</H3>" + "\n";
if (bmTreeNode.children.length > 0) {
out = out + tmp;
out = out + "\t".repeat(level) + "<DL><p>" + "\n";
for (const child of bmTreeNode.children) {
out = out + rec2HtmlStr(child, level + 1);
}
out = out + "\t".repeat(level) + "</DL><p>" + "\n";
}
}
if (level === 1) {
return (
"<!DOCTYPE NETSCAPE-Bookmark-file-1>" +
"\n" +
"<!-- This is an automatically generated file." +
"\n" +
" It will be read and overwritten." +
"\n" +
" DO NOT EDIT! -->" +
"\n" +
'<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">' +
"\n" +
'<meta http-equiv="Content-Security-Policy"' +
"\n" +
" content=\"default-src 'self'; script-src 'none'; img-src data: *; object-src 'none'\"></meta>" +
"\n" +
"<TITLE>Bookmarks</TITLE>" +
"\n" +
"<H1>Bookmarks Menu</H1>" +
"\n" +
"\n" +
"<DL><p>" +
"\n" +
out +
"</DL>"
);
}
return out;
}

async function exportHTML(bookmarkId) {
if (typeof bookmarkId !== "string") {
bookmarkId = "root________";
}
const data = (await browser.bookmarks.getSubTree(bookmarkId))[0];

const content = unescape(encodeURIComponent(rec2HtmlStr(data)));
let dl = document.createElement("a");
let textFileAsBlob = new Blob([content], { type: "text/plain" });
dl.setAttribute("href", window.URL.createObjectURL(textFileAsBlob));
dl.setAttribute(
"download",
"export " + (bookmarkId === "root________" ? "all" : data.title) + ".html"
);
dl.setAttribute("visibility", "hidden");
dl.setAttribute("display", "none");
document.body.appendChild(dl);
dl.click();
document.body.removeChild(dl);
}

browser.menus.create({
title: "Export ALL (JSON)",
contexts: ["bookmark"],
onclick: (info, tab) => {
exportJSON();
},
});

browser.menus.create({
title: "Export ALL (HTML)",
contexts: ["bookmark"],
onclick: (info, tab) => {
exportHTML();
},
});

browser.menus.create({
title: "Export Branch (JSON)",
contexts: ["bookmark"],
onclick: (info, tab) => {
exportJSON(info.bookmarkId);
},
});

browser.menus.create({
title: "Export Branch (HTML)",
contexts: ["bookmark"],
onclick: (info, tab) => {
exportHTML(info.bookmarkId);
},
});

browser.menus.create({
title: "Import Branch (JSON)",
contexts: ["bookmark"],
onclick: (info, tab) => {
browser.tabs.create({
url: "options.html?type=json&bookmarkId=" + info.bookmarkId,
});
},
});

browser.menus.create({
title: "Import Branch (HTML)",
contexts: ["bookmark"],
onclick: (info, tab) => {
browser.tabs.create({
url: "options.html?type=html&bookmarkId=" + info.bookmarkId,
});
},
});
7 changes: 2 additions & 5 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
"manifest_version": 2,
"description": "Import or export a branch of the bookmark tree as a JSON or HTML file",
"name": "Bookmark Branch Porter",
"permissions": ["bookmarks"],
"options_ui": {
"page": "options.html"
},
"version": "1.3.14"
"permissions": ["menus", "bookmarks"],
"version": "1.4.14"
}
61 changes: 4 additions & 57 deletions options.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,69 +2,16 @@
<head>
<meta content="text/html;charset=utf-8" />
<style>
input[type="file"] {
float: right;
}
body {
background-color: lightgray;
padding: 3%;
text-align: center;
}
#impbtn,
#expbtn {
width: 50%;
margin-left: 25%;
text-align: center;
}
#impbtnhtml,
#expbtnhtml {
margin-left: 25%;
width: 50%;
text-align: center;
}
#impfolders,
#expfolders {
width: 100%;
text-align: center;
#impbtn {
display: none;
}
</style>
</head>
<body>
<fieldset>
<legend><b>Export Bookmarks</b></legend>
<select id="expfolders">
<option value="root________">Select Folder (optional)</option>
</select>
</fieldset>
<fieldset>
<input id="expbtn" type="button" value="Export JSON" />
</fieldset>
<fieldset>
<input id="expbtnhtml" type="button" value="Export HTML" />
</fieldset>
<fieldset>
<div id="expstatus"></div>
</fieldset>

--- or ---

<fieldset>
<legend><b>Import Bookmarks</b></legend>
<select id="impfolders">
<option value="">Select Import Folder (required)</option>
</select>
</fieldset>
<fieldset>
<label for="impbtn">Select JSON</label>
<input id="impbtn" type="file" value="" disabled />
</fieldset>
<fieldset>
<label for="impbtnhtml">Select HTML</label>
<input id="impbtnhtml" type="file" value="" disabled />
</fieldset>
<fieldset>
<div id="impstatus"></div>
</fieldset>

<h2>This Tab will close, when the Import is done</h2>
<input id="impbtn" type="file" value="" />
<script src="options.js"></script>
</body>
Loading

0 comments on commit f1a3286

Please sign in to comment.