Register commands and URL-regexes separately

This allows easy re-use of commands, tying names
to URL-regexes rather than command-strings.
Much more user-friendly, I reckon!

Also, now we use “$URL” instead of “%s” for URL
substitution in commands. More shelly that way.
This commit is contained in:
Jaidyn Ann 2024-03-02 13:25:06 -06:00
parent 40b5ae16cb
commit 45462ffa98
3 changed files with 144 additions and 44 deletions

View File

@ -16,18 +16,20 @@ function getUrlCommand(url) {
let matchRegex = ""; let matchRegex = "";
try { try {
let savedCommands = JSON.parse(localStorage.getItem("commands")); let savedCommands = JSON.parse(localStorage.getItem("commands"));
let savedRegexRules = JSON.parse(localStorage.getItem("urlRules"));
// Find the most-applicable command… // Find the most-applicable command…
for (regexCommandPair of savedCommands) { for (regexCommandIPair of savedRegexRules) {
let regex = regexCommandPair[0]; let regex = regexCommandIPair[0];
let match = url.match(regex); let match = url.match(regex);
let compared = compareRegexComplexity(matchRegex, regex); let compared = compareRegexComplexity(matchRegex, regex);
if (match && (compared == 0 || compared == 1)) { if (match && (compared == 0 || compared == 1)) {
matchCommand = regexCommandPair[1]; let command_i = regexCommandIPair[1];
matchCommand = savedCommands[command_i][1];
matchRegex = regex; matchRegex = regex;
} }
} }
// … and replace the substitution-string with the URL. // … and replace the substitution-string with the URL.
matchCommand = matchCommand.replaceAll("%s", url); matchCommand = matchCommand.replaceAll("$URL", url);
} catch {}; } catch {};
return matchCommand; return matchCommand;
} }

View File

@ -1,24 +1,34 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<meta charset="utf8">
</head>
<body> <body>
<section>
<h3>Shell commands</h3>
<p>Add shell commands, to be executed with a pages URL as its argument. In a command, $URL will be replaced with the target pages URL.</p>
<table id="commandTable"> <table id="commandTable">
<tr>
<th>Name</th>
<th>Shell command</th>
</tr>
</table>
<button style="width: 5em;" id="save-cmd">Apply</button>
</section>
<section>
<h3>URL/Page rules</h3>
<p>Associate the above commands with URLs, based on regex rules. When a URL is tied to a command, a button will appear in context-menus and the address bar to run said command.</p>
<table id="regexTable">
<tr> <tr>
<th>URL regex</th> <th>URL regex</th>
<th>Shell command</th> <th>Shell command</th>
</tr> </tr>
<!-- <tr class="regexCommandRow">
<td>
<input type="text" class="regex" name="color"
placeholder="https://example.com/*"/>
</td>
<td>
<input type="text" class="command" name="color"
placeholder="curl %s > /tmp/example" />
</td>
</tr> -->
</table> </table>
<button style="width: 5em;" id="save-regex">Apply</button>
</section>
<button id="save">Apply</button>
<script src="options.js"></script> <script src="options.js"></script>
</body> </body>

View File

@ -1,25 +1,50 @@
// Given the name of an array saved to localStorage, return it (if possible).
function savedArray(name) {
let saved = [];
try {
saved = JSON.parse(localStorage.getItem(name));
return saved;
} catch { };
return saved;
}
// Iterate over the commands-table and save each of the users valid // Iterate over the commands-table and save each of the users valid
// regex+command rows to storage. // name+command rows to storage.
function saveCommands() { function saveCommands() {
let commands = []; let commands = [];
for (commandTr of document.getElementsByClassName("regexCommandRow")) { for (commandTr of document.getElementsByClassName("nameCommandRow")) {
let regex = commandTr.getElementsByClassName("regex")[0].value; let name = commandTr.getElementsByClassName("name")[0].value;
let command = commandTr.getElementsByClassName("command")[0].value; let command = commandTr.getElementsByClassName("command")[0].value;
if (regex && command) if (name && command)
commands.push([regex, command]); commands.push([name, command]);
} }
localStorage.setItem("commands", JSON.stringify(commands)); localStorage.setItem("commands", JSON.stringify(commands));
} }
// Read the users saved command-regex pairs from storage, and populate the // Iterate over the regex-table and save each of the users valid
// regex+command-index rows to storage.
function saveRegexRules() {
let rules = [];
for (regexTr of document.getElementsByClassName("regexCommandRow")) {
let regex = regexTr.getElementsByClassName("regex")[0].value;
let command_i = regexTr.getElementsByClassName("commandMenu")[0].value;
if (regex && command_i)
rules.push([regex, command_i]);
}
localStorage.setItem("urlRules", JSON.stringify(rules));
}
// Read the users saved name+command pairs from storage, and populate the
// command-table with them. // command-table with them.
function populateCommandTable() { function populateCommandTable() {
let commandTable = document.getElementById("commandTable"); let commandTable = document.getElementById("commandTable");
try { try {
let savedCommands = JSON.parse(localStorage.getItem("commands")); let savedCommands = savedArray("commands");
for (cmdRegex of savedCommands) { for (cmdName of savedCommands) {
let commandTr = createCommandTr(cmdRegex[0], cmdRegex[1]); let commandTr = createCommandTr(cmdName[0], cmdName[1]);
commandTable.appendChild(commandTr); commandTable.appendChild(commandTr);
} }
} catch { }; } catch { };
@ -28,30 +53,57 @@ function populateCommandTable() {
} }
// Read the users saved regex+command-index pairs from storage, and populate the
// command-table with them.
function populateRegexTable() {
let regexTable = document.getElementById("regexTable");
try {
let savedRegex = savedArray("urlRules");
for (let i = 0; i < savedRegex.length; i++) {
let regexTr = createRegexTr(savedRegex[i][0], savedRegex[i][1], createCommandMenu());
regexTable.appendChild(regexTr);
}
} catch { };
// Always, again, have a spare tire!!
regexTable.appendChild(createRegexTr("", "", createCommandMenu()));
}
// Create a <select> drop-down menu containing all of the users commands.
function createCommandMenu() {
let commandMenu = document.createElement("SELECT");
commandMenu.setAttribute("class", "commandMenu");
commandMenu.setAttribute("type", "text");
let savedCommands = savedArray("commands");
for (let i = 0; i < savedCommands.length; i++) {
let commandOption = document.createElement("OPTION");
commandOption.setAttribute("value", i);
commandOption.text = savedCommands[i][0];
commandMenu.appendChild(commandOption);
}
return commandMenu;
}
// 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.
function createCommandTr(regex, command) { function createRegexTr(regex, command_i, commandMenu) {
let regexInput = document.createElement("INPUT"); let regexInput = document.createElement("INPUT");
regexInput.setAttribute("class", "regex"); regexInput.setAttribute("class", "regex");
regexInput.setAttribute("type", "text"); regexInput.setAttribute("type", "text");
regexInput.setAttribute("placeholder", "https://example.com/*"); regexInput.setAttribute("placeholder", "https://example.org/.*");
if (regex && command) if (regex && command_i)
regexInput.setAttribute("value", regex); regexInput.setAttribute("value", regex);
let regexTd = document.createElement("TD"); let regexTd = document.createElement("TD");
regexTd.appendChild(regexInput); regexTd.appendChild(regexInput);
let commandInput = document.createElement("INPUT");
commandInput.setAttribute("class", "command");
commandInput.setAttribute("type", "text");
commandInput.setAttribute("placeholder", "curl %s > /tmp/downloaded");
if (regex && command)
commandInput.setAttribute("value", command);
let commandTd = document.createElement("TD"); let commandTd = document.createElement("TD");
commandTd.appendChild(commandInput); try {
commandMenu.childNodes[command_i].setAttribute("selected", true);
} catch { };
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);
@ -60,12 +112,48 @@ function createCommandTr(regex, command) {
} }
// 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
// have no value.
function createCommandTr(name, command) {
let nameInput = document.createElement("INPUT");
nameInput.setAttribute("class", "name");
nameInput.setAttribute("type", "text");
nameInput.setAttribute("placeholder", "Curl");
if (name && command)
nameInput.setAttribute("value", name);
let nameTd = document.createElement("TD");
nameTd.appendChild(nameInput);
let commandInput = document.createElement("INPUT");
commandInput.setAttribute("class", "command");
commandInput.setAttribute("type", "text");
commandInput.setAttribute("placeholder", "curl $URL > /tmp/downloaded");
if (name && command)
commandInput.setAttribute("value", command);
let commandTd = document.createElement("TD");
commandTd.appendChild(commandInput);
let tr = document.createElement("TR");
tr.setAttribute("class", "nameCommandRow");
tr.appendChild(nameTd);
tr.appendChild(commandTd);
return tr;
}
document.addEventListener("click", e => { document.addEventListener("click", e => {
if (e.target.id == ("save")) { if (e.target.id == ("save-cmd")) {
saveCommands(); saveCommands();
location.reload(); location.reload();
} else if (e.target.id == ("save-regex")) {
saveRegexRules();
location.reload();
} }
}); });
populateCommandTable(); populateCommandTable();
populateRegexTable();