ebrowser v1.0.51: download.json to add user-defined context-menu

This commit is contained in:
James Feng Cao 2024-06-30 17:04:50 +08:00
parent f3ea023929
commit 5e3172ece0
16 changed files with 118 additions and 45 deletions

View file

@ -5,7 +5,8 @@ Ebrowser is designed with the philosophy of [Android uweb browser](https://githu
- much less memory footprint than edge/chrome browser and highly performant.
- keyboard friendly with vim-style keymaps and command line support in address bar.
- [global redirection](https://uweb.surge.sh/en/redirect/index.html#) to bypass censorship.
- user scripts at will. Ex. pressing "md" in no-focus mode to preview markdown file.
- user CSS/JS at will. Ex. pressing "md" in no-focus mode to preview markdown file.
- global CSS/JS for all sites at will.
- CSS/JS for domains, similar to [uweb](https://jamesfengcao.gitlab.io/uweb/en/sitejs/index.html), but use sitejs/[domain].js or sitecss/[domain].css, not [domain root].js/css.
- customizable.
@ -74,7 +75,7 @@ Like any popular browser, the very first word in address bar if defined in "sear
- np : no proxy.
- up [proxyName] : use proxy. privous proxy or the first proxy in proxy.json w/o [proxyName]. ":up" command also disables global and domain redirections, which are not restored by ":np".
- ua [useragentName] : set user agent for future tabs. default user agent w/o arguments.
- update [updateurl] : update the app. updateurl is optional.
- update [filename] : update the app w/o argument, otherwise retrive the [filename] from remote. The filename could be any file on [mirror sites](https://jamesfengcao.gitlab.io/uweb/en/readme/index.html) (this repository is part of it).
- pdf [filename w/o extension] {[options](https://www.electronjs.org/docs/latest/api/web-contents#contentsprinttopdfoptions)} : print to PDF file. All arguments are optional; empty option "{}" to capture long screenshot as vector graphics.
- "!" address bar commands
"!xx ..." evaluates "xx.js" with the whole text as arguments[0].
@ -98,6 +99,7 @@ The other commands are defined in "mapkeys.json", which will map keys to address
- "mapkeys.json": keys-addressbarCommands pairs. The addressbar commands are multiple lines of address bar command separated by "\n".
- "proxy.json": name-[ProxyConfig](https://www.electronjs.org/docs/latest/api/structures/proxy-config) pairs
- "uas.json" : name-useragent pairs
- "download.json" : array of strings to define buttons for downloading dialog. The even-indexed strings are texts to show on the button. The odd-indexed strings are address bar commands with "%u" as the downloaded url.
#### Javascript at three levels
- Web page: url like "javascript:" or bookmarklet command ":bml" runs in web page.

View file

@ -71,6 +71,9 @@ You should have received a copy of the GNU General Public License along with thi
var bQueryHistory = false;
let sitecssP = path.join(__dirname,"sitecss");
let sitejsP = path.join(__dirname,"sitejs");
let gjsA = [];
let gcssA = [];
let gcssJSA = [];
var bDomainJS = fs.existsSync(sitejsP);
var bDomainCSS = fs.existsSync(sitecssP);
var autocMode = 0; //0 for substring, 1 for startsWith
@ -141,12 +144,16 @@ You should have received a copy of the GNU General Public License along with thi
tabs.children[iTab].classList.add('curWV');
}
async function loadJSFile(tab,jsF){
if(fs.existsSync(jsF)){
try {
let js = await fs.promises.readFile(jsF,'utf8');
tab.executeJavaScript(js,false);
}catch(e){}
}
}
async function loadCSSFile(tab,jsF){
try {
let js = await fs.promises.readFile(jsF,'utf8');
tab.insertCSS(css);
}catch(e){}
}
function cbStartLoading(e){
if(!bDomainCSS) return;
@ -158,14 +165,15 @@ You should have received a copy of the GNU General Public License along with thi
let jsF = path.join(sitecssP, domain+".js");
loadJSFile(tab,jsF);
jsF = path.join(sitecssP, domain+".css");
if(fs.existsSync(jsF)){
(async ()=>{
try {
let css = await fs.promises.readFile(jsF,'utf8');
tab.insertCSS(css);
}catch(e){}
})();
}
loadCSSFile(tab,jsF);
gcssA.forEach((fname)=>{
jsF = path.join(__dirname, fname);
loadCSSFile(tab,jsF);
});
gcssJSA.forEach((fname)=>{
jsF = path.join(__dirname, fname);
loadJSFile(tab,jsF);
});
}
function cbFinishLoad(e){
let tab = e.target;
@ -184,6 +192,10 @@ You should have received a copy of the GNU General Public License along with thi
let jsF = path.join(sitejsP, domain+".js");
loadJSFile(tab,jsF);
}
gjsA.forEach((fname)=>{
let jsF = path.join(__dirname, fname);
loadJSFile(tab,jsF);
});
}
function initTab(tab){
tab.allowpopups = true;

View file

@ -1,4 +1,4 @@
{"version":"1.0.45",
{"version":"1.0.51",
"name": "ebrowser",
"description": "The keyboard-friendly minimal suckless web browser",
"main": "webview.js",

View file

@ -9,6 +9,7 @@
"andi":"https://andisearch.com/?q=%s",
"ph":"https://phind-ai.com/search?q=%s",
"gf":"https://greasyfork.org/en/scripts?filter_locale=0&sort=updated&q=%s",
"repo":"https://www.awesome-repositories.com/s/results-with-ai/%s",
"dev":"https://devv.ai/search?agentMode=false&q=%s",
"you":"https://you.com/search?tbm=youchat&q=%s",
"p":"https://www.perplexity.ai/?q=%s",

View file

@ -50,6 +50,7 @@ var bForwardCookie = false;
var proxies = {};
var proxy;
var useragents = {};
var downloadMenus; //[]
var defaultUA =
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" +
process.versions.chrome +" Safari/537.36";
@ -115,10 +116,45 @@ async function createWindow () {
cmdlineProcess(process.argv, process.cwd(), 0);
//app.commandLine.appendSwitch ('trace-warnings');
fs.readFile(path.join(__dirname,'download.json'), 'utf8', (err, jsonStr) => {
if (err) return;
try {
downloadMenus = JSON.parse(jsonStr);
}catch (e){console.log(e)}
});
win.webContents.on('page-title-updated',(event,cmd)=>{
addrCommand(cmd);
});
session.defaultSession.on("will-download", (e, item) => {
//item.setSavePath(save)
if(!downloadMenus) return;
let buttons = ["OK", "Cancel", translate("Copy")];
buttons.push(downloadMenus.filter((item, index) => (index&1) === 0));
const button = dialog.showMessageBoxSync(mainWindow, {
"type": "question",
"title": translate("Download"),
"message": `Do you want to download the file?`,
"buttons": buttons,
"defaultId": 0,
});
switch(button) {
case 0:
return;
case 1:
break;
case 2:
clipboard.writeText(item.getURL());
break;
default:
let cmd = downloadMenus[2*button-5].replace('%u',item.getURL());
let js = `handleQuery(\`${cmd}\`)`;
win.webContents.executeJavaScript(js,false);
}
e.preventDefault();
});
win.webContents.on('console-message',cbConsoleMsg);
}
@ -238,12 +274,16 @@ function addrCommand(cmd){
case "update":
let updateurl;
if(1==args.length)
updateurl = repositoryurl;
updateApp(repositoryurl);
else {
updateurl = args[1];
if(!updateurl.endsWith("/")) updateurl = updateurl +"/";
filename = args[1];
let iSlash = filename.lastIndexOf('/');
if(iSlash>0){
let folder = path.join(__dirname,filename.substring(0,iSlash));
fs.mkdirSync(folder,{ recursive: true });
}
fetch2file(repositoryurl,filename);
}
updateApp(updateurl);
return;
}
}
@ -317,24 +357,36 @@ function cbTitleUpdate(event,title){
function menuArray(labelprefix, linkUrl){
const menuTemplate = [
{
label: labelprefix+'Open Link',
label: labelprefix+translate('Open'),
click: () => {
shell.openExternal(linkUrl);
}
},
{
label: labelprefix+'Copy Link',
label: labelprefix+translate('Copy'),
click: () => {
clipboard.writeText(linkUrl);
}
},
{
label: labelprefix+'Download',
label: labelprefix+translate('Download'),
click: () => {
win.contentView.children[i].webContents.downloadURL(linkUrl);
}
},
];
if(downloadMenus){
for(let i=0; i<downloadMenus.length-1;i++){
menuTemplate.push({
label: labelprefix+downloadMenus[i],
click: () => {
let cmd = downloadMenus[i+1].replace('%u',linkUrl);
let js = `handleQuery(\`${cmd}\`)`;
win.webContents.executeJavaScript(js,false);
}
});
}
}
return menuTemplate;
}