Compare commits
3 Enmetoj
a60d81009b
...
2c73b5a956
Author | SHA1 | Date | |
---|---|---|---|
Jaidyn Ann | 2c73b5a956 | ||
Jaidyn Ann | 0ba9d32915 | ||
Jaidyn Ann | 596b383a54 |
|
@ -101,6 +101,51 @@
|
||||||
"description": "Displayed placeholder for options-page input for regex."
|
"description": "Displayed placeholder for options-page input for regex."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"optionsTitleDownload": {
|
||||||
|
"message": "Download commands",
|
||||||
|
"description": "Title of options-page section for download commands."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsDescDownload": {
|
||||||
|
"message": "Assign commands to be executed for certain URLs (by regex) when downloads are initiated or finished. In commands, $URL will be replaced with the download’s URL, and $FILE with the target file.",
|
||||||
|
"description": "Description of options-page section for download commands."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsHeadDownloadRule": {
|
||||||
|
"message": "URL regex",
|
||||||
|
"description": "Header of table-element for options-page section for download commands."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsHeadDownloadCommand": {
|
||||||
|
"message": "Shell command",
|
||||||
|
"description": "Header of table-element for options-page section for download commands."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsHeadDownloadType": {
|
||||||
|
"message": "Run when…",
|
||||||
|
"description": "Header of table-element for options-page section for download commands."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsDownloadWhenStarted": {
|
||||||
|
"message": "… started",
|
||||||
|
"description": "Member of menu-list for options-page section for download commands. Completes the sentence, “Run when…”"
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsDownloadWhenFinished": {
|
||||||
|
"message": "… finished",
|
||||||
|
"description": "Member of menu-list for options-page section for download commands. Completes the sentence, “Run when…”"
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsPlaceholderDownloadRegex": {
|
||||||
|
"message": ".*.png",
|
||||||
|
"description": "Displayed placeholder for options-page input for download command’s regex."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsPlaceholderDownloadCommand": {
|
||||||
|
"message": "echo $URL > $FILE.url",
|
||||||
|
"description": "Displayed placeholder for options-page input for download command."
|
||||||
|
},
|
||||||
|
|
||||||
"optionsSaveButton": {
|
"optionsSaveButton": {
|
||||||
"message": "Apply",
|
"message": "Apply",
|
||||||
"description": "Name of button in options-page to save changes."
|
"description": "Name of button in options-page to save changes."
|
||||||
|
|
|
@ -101,6 +101,51 @@
|
||||||
"description": "Provizora valoro ĉe agordopaĝo por enigo de reteja regula esprimo."
|
"description": "Provizora valoro ĉe agordopaĝo por enigo de reteja regula esprimo."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"optionsTitleDownload": {
|
||||||
|
"message": "Elŝutaj ŝel-ordonoj",
|
||||||
|
"description": "Titolo de agordo-parto por elŝutaj ordonoj."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsDescDownload": {
|
||||||
|
"message": "Agordi ordonojn kiuj ruliĝu dum komenciĝo aŭ finiĝo de elŝutado, laŭ URL (regulesprime). En ordonoj, «$URL» anstataŭiĝos per la elŝuta URL, kaj «$FILE» per la elŝuta dosiervojo.",
|
||||||
|
"description": "Priskribo de agordo-parto por elŝutaj ordonoj."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsHeadDownloadRule": {
|
||||||
|
"message": "URL regula esprimo",
|
||||||
|
"description": "Titolo de tabelo-kolumno ĉe agordo-parto por elŝutaj ordonoj."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsHeadDownloadCommand": {
|
||||||
|
"message": "Ŝel-ordono",
|
||||||
|
"description": "Titolo de tabelo-kolumno ĉe agordo-parto por elŝutaj ordonoj."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsHeadDownloadType": {
|
||||||
|
"message": "Rulu je…",
|
||||||
|
"description": "Titolo de tabelo-kolumno ĉe agordo-parto por elŝutaj ordonoj."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsDownloadWhenStarted": {
|
||||||
|
"message": "… komenciĝo",
|
||||||
|
"description": "Menuero ĉe agordo-parto por elŝutaj ordonoj. Finas la frazon, «Rulu je…»"
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsDownloadWhenFinished": {
|
||||||
|
"message": "… finiĝo",
|
||||||
|
"description": "Menuero ĉe agordo-parto por elŝutaj ordonoj. Finas la frazon, «Rulu je…»"
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsPlaceholderDownloadRegex": {
|
||||||
|
"message": ".*.png",
|
||||||
|
"description": "Provizora valoro ĉe agordopaĝo por enigo de regula esprimo por elŝuta ordono."
|
||||||
|
},
|
||||||
|
|
||||||
|
"optionsPlaceholderDownloadCommand": {
|
||||||
|
"message": "echo $URL > $FILE.url",
|
||||||
|
"description": "Provizora valoro ĉe agordopaĝo por enigo de elŝuta ordono."
|
||||||
|
},
|
||||||
|
|
||||||
"optionsSaveButton": {
|
"optionsSaveButton": {
|
||||||
"message": "Konservi",
|
"message": "Konservi",
|
||||||
"description": "Nomo de butono ĉe agordopaĝo por konservi ŝanĝojn."
|
"description": "Nomo de butono ĉe agordopaĝo por konservi ŝanĝojn."
|
||||||
|
|
|
@ -48,12 +48,42 @@ function getUrlCommands(url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Execute the given command string, subsituting “$URL” with the given url.
|
// Return the download-command string (if any) associated with a URL and type
|
||||||
function runCommand(command, url) {
|
// integer (0→started; 1→finished).
|
||||||
|
function getDownloadCommand(url, type) {
|
||||||
|
let matchCommand = undefined;
|
||||||
|
let matchRegex = "";
|
||||||
|
try {
|
||||||
|
let savedDownloads = savedArray("downloadCommands");
|
||||||
|
// Find the most-applicable command.
|
||||||
|
for (regexCommandType of savedDownloads) {
|
||||||
|
let regex = regexCommandType[0];
|
||||||
|
let match = url.match(regex);
|
||||||
|
|
||||||
|
let compared = compareRegexComplexity(matchRegex, regex);
|
||||||
|
if ((match && (compared == 0 || compared == 1))
|
||||||
|
&& (regexCommandType[2] == type))
|
||||||
|
{
|
||||||
|
matchCommand = regexCommandType[1];
|
||||||
|
matchRegex = regex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {};
|
||||||
|
return matchCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Execute the given command string, subsituting “$URL” with url and
|
||||||
|
// “$FILE” with filepath.
|
||||||
|
function runCommand(command, url, filepath) {
|
||||||
if (!port)
|
if (!port)
|
||||||
initShellfoxProgram();
|
initShellfoxProgram();
|
||||||
if (command && port)
|
if (command && port)
|
||||||
port.postMessage(command.replaceAll("$URL", url));
|
port.postMessage(command
|
||||||
|
.replaceAll("$URL", url)
|
||||||
|
.replaceAll("${URL}", url)
|
||||||
|
.replaceAll("$FILE", filepath)
|
||||||
|
.replaceAll("${FILE}", filepath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,8 +131,9 @@ function hideLinkContextMenuItem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// (Re-)Create the menu-items for each context menu.
|
||||||
function createCommandMenuItems() {
|
function createCommandMenuItems() {
|
||||||
let savedCommands = savedArray("commands");
|
let savedCommands = savedArray("commands") || [];
|
||||||
for (let i = 0; i < savedCommands.length; i++) {
|
for (let i = 0; i < savedCommands.length; i++) {
|
||||||
let nameCommandPair = savedCommands[i];
|
let nameCommandPair = savedCommands[i];
|
||||||
let name = nameCommandPair[0];
|
let name = nameCommandPair[0];
|
||||||
|
@ -215,6 +246,26 @@ browser.menus.onClicked.addListener((info, tab) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// When a download starts, run any applicable download commands.
|
||||||
|
browser.downloads.onCreated.addListener((downloadItem) => {
|
||||||
|
let command = getDownloadCommand(downloadItem.url, 0);
|
||||||
|
if (command)
|
||||||
|
runCommand(command, downloadItem.url, downloadItem.filename);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// When a download completes, run any applicable download commands.
|
||||||
|
browser.downloads.onChanged.addListener((downloadDelta) => {
|
||||||
|
browser.downloads.search({ "id": downloadDelta.id }).then((downloadItems) => {
|
||||||
|
if (downloadDelta.state.current == "complete" && downloadItems.length > 0) {
|
||||||
|
let command = getDownloadCommand(downloadItems[0].url, 1);
|
||||||
|
if (command)
|
||||||
|
runCommand(command, downloadItems[0].url, downloadItems[0].filename);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Whenever settings (commands) are updated, repopulate context-menus’ items.
|
// Whenever settings (commands) are updated, repopulate context-menus’ items.
|
||||||
window.addEventListener("storage", (e) => {
|
window.addEventListener("storage", (e) => {
|
||||||
createCommandMenuItems();
|
createCommandMenuItems();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "__MSG_extensionName__",
|
"name": "__MSG_extensionName__",
|
||||||
"version": "0.1",
|
"version": "0.12",
|
||||||
|
|
||||||
"description": "__MSG_extensionDescription__",
|
"description": "__MSG_extensionDescription__",
|
||||||
"homepage_url": "https://hak.xwx.moe/jadedctrl/shellfox",
|
"homepage_url": "https://hak.xwx.moe/jadedctrl/shellfox",
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"activeTab",
|
"activeTab",
|
||||||
|
"downloads",
|
||||||
"nativeMessaging",
|
"nativeMessaging",
|
||||||
"menus",
|
"menus",
|
||||||
"tabs"
|
"tabs"
|
||||||
|
|
17
options.html
17
options.html
|
@ -4,6 +4,7 @@
|
||||||
<meta charset="utf8">
|
<meta charset="utf8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<article>
|
||||||
<section>
|
<section>
|
||||||
<h3 id="commandTitle">Shell commands</h3>
|
<h3 id="commandTitle">Shell commands</h3>
|
||||||
<p id="commandP">Add shell commands, to be executed with a page’s URL as its argument. In a command, $URL will be replaced with the target page’s URL.</p>
|
<p id="commandP">Add shell commands, to be executed with a page’s URL as its argument. In a command, $URL will be replaced with the target page’s URL.</p>
|
||||||
|
@ -28,6 +29,22 @@
|
||||||
</table>
|
</table>
|
||||||
<button style="width: 5em;" id="save-regex">Apply</button>
|
<button style="width: 5em;" id="save-regex">Apply</button>
|
||||||
</section>
|
</section>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<h3 id="downloadTitle">Download commands</h3>
|
||||||
|
<p id="downloadP">Assign commands to be executed for certain URLs (by regex) when downloads are initiated or finished. In commands, $URL will be replaced with the download’s URL, and $FILE with the target file.</p>
|
||||||
|
<table id="downloadTable">
|
||||||
|
<tr>
|
||||||
|
<th id="downloadTypeTh">On start/finish</th>
|
||||||
|
<th id="downloadRegexTh">URL regex</th>
|
||||||
|
<th id="downloadShellTh">Shell command</th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button style="width: 5em;" id="save-downloads">Apply</button>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
|
||||||
<script src="options.js"></script>
|
<script src="options.js"></script>
|
||||||
|
|
109
options.js
109
options.js
|
@ -35,6 +35,22 @@ function saveRegexRules() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Iterate over the commands-table and save each of the user’s valid
|
||||||
|
// name+command rows to storage.
|
||||||
|
function saveDownloadCommands() {
|
||||||
|
let downloads = [];
|
||||||
|
for (downloadTr of document.getElementsByClassName("downloadCommandRow")) {
|
||||||
|
let regex = downloadTr.getElementsByClassName("regex")[0].value;
|
||||||
|
let command = downloadTr.getElementsByClassName("command")[0].value;
|
||||||
|
let type = downloadTr.getElementsByClassName("startFinishMenu")[0].value;
|
||||||
|
if (regex && command && type)
|
||||||
|
downloads.push([regex, command, type]);
|
||||||
|
}
|
||||||
|
console.log(downloads);
|
||||||
|
localStorage.setItem("downloadCommands", JSON.stringify(downloads));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Read the user’s saved name+command pairs from storage, and populate the
|
// Read the user’s saved name+command pairs from storage, and populate the
|
||||||
// command-table with them.
|
// command-table with them.
|
||||||
function populateCommandTable() {
|
function populateCommandTable() {
|
||||||
|
@ -67,13 +83,29 @@ function populateRegexTable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Read the user’s saved type+name+command pairs from storage, and populate the
|
||||||
|
// downloads-table with them.
|
||||||
|
function populateDownloadTable() {
|
||||||
|
let downloadTable = document.getElementById("downloadTable");
|
||||||
|
try {
|
||||||
|
let savedDownloads = savedArray("downloadCommands") || [];
|
||||||
|
for (regexCommandType of savedDownloads) {
|
||||||
|
let downloadTr = createDownloadTr(regexCommandType[0], regexCommandType[1], regexCommandType[2]);
|
||||||
|
downloadTable.appendChild(downloadTr);
|
||||||
|
}
|
||||||
|
} catch {};
|
||||||
|
// And yet again! Have spares!!!
|
||||||
|
downloadTable.appendChild(createDownloadTr("", "", 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create a <select> drop-down menu containing all of the user’s commands.
|
// Create a <select> drop-down menu containing all of the user’s commands.
|
||||||
function createCommandMenu() {
|
function createCommandMenu() {
|
||||||
let commandMenu = document.createElement("SELECT");
|
let commandMenu = document.createElement("SELECT");
|
||||||
commandMenu.setAttribute("class", "commandMenu");
|
commandMenu.setAttribute("class", "commandMenu");
|
||||||
commandMenu.setAttribute("type", "text");
|
commandMenu.setAttribute("type", "text");
|
||||||
|
|
||||||
let savedCommands = savedArray("commands");
|
let savedCommands = savedArray("commands") || [];
|
||||||
for (let i = 0; i < savedCommands.length; i++) {
|
for (let i = 0; i < savedCommands.length; i++) {
|
||||||
let commandOption = document.createElement("OPTION");
|
let commandOption = document.createElement("OPTION");
|
||||||
commandOption.setAttribute("value", i);
|
commandOption.setAttribute("value", i);
|
||||||
|
@ -84,6 +116,66 @@ function createCommandMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function createDownloadTypeMenu(type) {
|
||||||
|
let typeMenu = document.createElement("SELECT");
|
||||||
|
typeMenu.setAttribute("class", "startFinishMenu");
|
||||||
|
typeMenu.setAttribute("type", "text");
|
||||||
|
|
||||||
|
let onStartOption = document.createElement("OPTION");
|
||||||
|
onStartOption.setAttribute("value", 0);
|
||||||
|
onStartOption.text = browser.i18n.getMessage("optionsDownloadWhenStarted");
|
||||||
|
typeMenu.appendChild(onStartOption);
|
||||||
|
|
||||||
|
let onEndOption = document.createElement("OPTION");
|
||||||
|
onEndOption.setAttribute("value", 1);
|
||||||
|
onEndOption.text = browser.i18n.getMessage("optionsDownloadWhenFinished");
|
||||||
|
typeMenu.appendChild(onEndOption);
|
||||||
|
|
||||||
|
try {
|
||||||
|
typeMenu.childNodes[type].setAttribute("selected", true);
|
||||||
|
} catch { };
|
||||||
|
|
||||||
|
return typeMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function createDownloadTr(regex, command, type) {
|
||||||
|
let typeMenu = createDownloadTypeMenu(type);
|
||||||
|
|
||||||
|
let typeTd = document.createElement("TD");
|
||||||
|
typeTd.appendChild(typeMenu);
|
||||||
|
|
||||||
|
let regexInput = document.createElement("INPUT");
|
||||||
|
regexInput.setAttribute("class", "regex");
|
||||||
|
regexInput.setAttribute("type", "text");
|
||||||
|
regexInput.setAttribute("placeholder",
|
||||||
|
browser.i18n.getMessage("optionsPlaceholderDownloadRegex"));
|
||||||
|
if (regex && command && type)
|
||||||
|
regexInput.setAttribute("value", regex);
|
||||||
|
|
||||||
|
let regexTd = document.createElement("TD");
|
||||||
|
regexTd.appendChild(regexInput);
|
||||||
|
|
||||||
|
let commandInput = document.createElement("INPUT");
|
||||||
|
commandInput.setAttribute("class", "command");
|
||||||
|
commandInput.setAttribute("type", "text");
|
||||||
|
commandInput.setAttribute("placeholder",
|
||||||
|
browser.i18n.getMessage("optionsPlaceholderDownloadCommand"));
|
||||||
|
if (regex && command && type)
|
||||||
|
commandInput.setAttribute("value", command);
|
||||||
|
|
||||||
|
let commandTd = document.createElement("TD");
|
||||||
|
commandTd.appendChild(commandInput);
|
||||||
|
|
||||||
|
let tr = document.createElement("TR");
|
||||||
|
tr.setAttribute("class", "downloadCommandRow");
|
||||||
|
tr.appendChild(typeTd);
|
||||||
|
tr.appendChild(regexTd);
|
||||||
|
tr.appendChild(commandTd);
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create a table-row for the command-table, with the command & regex inputs’
|
// Create a table-row for the command-table, with the command & regex inputs’
|
||||||
// values set to the given parameters. If they are undefined, the inputs will
|
// values set to the given parameters. If they are undefined, the inputs will
|
||||||
// have no value.
|
// have no value.
|
||||||
|
@ -97,11 +189,13 @@ function createRegexTr(regex, command_i, commandMenu) {
|
||||||
|
|
||||||
let regexTd = document.createElement("TD");
|
let regexTd = document.createElement("TD");
|
||||||
regexTd.appendChild(regexInput);
|
regexTd.appendChild(regexInput);
|
||||||
|
|
||||||
let commandTd = document.createElement("TD");
|
let commandTd = document.createElement("TD");
|
||||||
try {
|
try {
|
||||||
commandMenu.childNodes[command_i].setAttribute("selected", true);
|
commandMenu.childNodes[command_i].setAttribute("selected", true);
|
||||||
} catch { };
|
} catch { };
|
||||||
commandTd.appendChild(commandMenu);
|
commandTd.appendChild(commandMenu);
|
||||||
|
|
||||||
let tr = document.createElement("TR");
|
let tr = document.createElement("TR");
|
||||||
tr.setAttribute("class", "regexCommandRow");
|
tr.setAttribute("class", "regexCommandRow");
|
||||||
tr.appendChild(regexTd);
|
tr.appendChild(regexTd);
|
||||||
|
@ -156,8 +250,15 @@ function i18nPage() {
|
||||||
document.getElementById("ruleRegexTh").innerText = browser.i18n.getMessage("optionsHeadRuleName");
|
document.getElementById("ruleRegexTh").innerText = browser.i18n.getMessage("optionsHeadRuleName");
|
||||||
document.getElementById("ruleShellTh").innerText = browser.i18n.getMessage("optionsHeadRuleCommand");
|
document.getElementById("ruleShellTh").innerText = browser.i18n.getMessage("optionsHeadRuleCommand");
|
||||||
|
|
||||||
|
document.getElementById("downloadTitle").innerText = browser.i18n.getMessage("optionsTitleDownload");
|
||||||
|
document.getElementById("downloadP").innerText = browser.i18n.getMessage("optionsDescDownload");
|
||||||
|
document.getElementById("downloadRegexTh").innerText = browser.i18n.getMessage("optionsHeadDownloadRule");
|
||||||
|
document.getElementById("downloadTypeTh").innerText = browser.i18n.getMessage("optionsHeadDownloadType");
|
||||||
|
document.getElementById("downloadShellTh").innerText = browser.i18n.getMessage("optionsHeadDownloadCommand");
|
||||||
|
|
||||||
document.getElementById("save-cmd").innerText = browser.i18n.getMessage("optionsSaveButton");
|
document.getElementById("save-cmd").innerText = browser.i18n.getMessage("optionsSaveButton");
|
||||||
document.getElementById("save-regex").innerText = browser.i18n.getMessage("optionsSaveButton");
|
document.getElementById("save-regex").innerText = browser.i18n.getMessage("optionsSaveButton");
|
||||||
|
document.getElementById("save-downloads").innerText = browser.i18n.getMessage("optionsSaveButton");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,10 +269,14 @@ document.addEventListener("click", e => {
|
||||||
} else if (e.target.id == ("save-regex")) {
|
} else if (e.target.id == ("save-regex")) {
|
||||||
saveRegexRules();
|
saveRegexRules();
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
} else if (e.target.id == ("save-downloads")) {
|
||||||
|
saveDownloadCommands();
|
||||||
|
location.reload();
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
populateCommandTable();
|
populateCommandTable();
|
||||||
populateRegexTable();
|
populateRegexTable();
|
||||||
|
populateDownloadTable();
|
||||||
i18nPage();
|
i18nPage();
|
||||||
|
|
Ŝarĝante…
Reference in New Issue