mirror of
https://github.com/torappinfo/uweb.git
synced 2024-08-14 23:54:59 +00:00
Compare commits
No commits in common. "c60d325354c3b477aa31f02207e1b0e89a64db1e" and "536ff07ffafc65140fca3683a710e95b74fb5245" have entirely different histories.
c60d325354
...
536ff07ffa
10 changed files with 186 additions and 111 deletions
116
ebrowser.md
Normal file
116
ebrowser.md
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
### [Ebrowser](https://github.com/torappinfo/ebrowser): keyboard-friendly minimal suckless web browser
|
||||||
|
Ebrowser is designed with the philosophy of [Android uweb browser](https://github.com/torappinfo/uweb) ([gitlab](https://gitlab.com/jamesfengcao/uweb)).
|
||||||
|
|
||||||
|
- lightweight (less than 20k bytes) without bundled electron.
|
||||||
|
- 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 "tr" to translate the page (need mapkeys.json config).
|
||||||
|
- customizable.
|
||||||
|
|
||||||
|
Note: Usually electron apps are heavyweight as they use browsers for simple things. Ebrowser uses core chromium effectively and very lightweight. Recommend to install electron separately.
|
||||||
|
|
||||||
|
#### Installing (for Windows, MacOS and Linux)
|
||||||
|
##### Install with prebuilt binaries
|
||||||
|
You can find prebuilt binaries [here](https://github.com/torappinfo/ebrowser/releases).
|
||||||
|
|
||||||
|
##### Install with nodejs
|
||||||
|
|
||||||
|
npm install electron
|
||||||
|
npm install ebrowser
|
||||||
|
|
||||||
|
Run ebrowser
|
||||||
|
|
||||||
|
electron ~/node_modules/ebrowser
|
||||||
|
|
||||||
|
Later on, you can run "npm install electron" to update electron/chromium or "npm install ebrowser" to update ebrowser independently.
|
||||||
|
|
||||||
|
##### Update app quickly without updating chromium
|
||||||
|
Pressing "Alt" to show the menu bar and choose "Check for updates" under "Help". OR
|
||||||
|
|
||||||
|
Type ":update" in the address bar and press "enter" key to update.
|
||||||
|
|
||||||
|
Mirror urls could be used like ":update https://uwebzh.netlify.app/misc/ebrowser". All the mirrors listed on [uweb browser](https://uwebzh.netlify.app/en/readme/index.html) could be used. The update url needs to be changed accordingly to be the folder "misc/ebrowser" under the mirror site root url.
|
||||||
|
|
||||||
|
#### Key shortcuts
|
||||||
|
- CTRL+C: stop loading
|
||||||
|
- CTRL+G: address bar to show page url
|
||||||
|
- CTRL+L: focus to address bar
|
||||||
|
- CTRL+T: new Tab
|
||||||
|
- CTRL+SHIFT+T: restore closed Tab
|
||||||
|
- CTRL+TAB: switch to next tab
|
||||||
|
- CTRL+SHIFT+TAB: switch to previous tab
|
||||||
|
- CTRL+W: close Tab
|
||||||
|
- ALT+<-: go backward
|
||||||
|
- ALT+->: go forward
|
||||||
|
- CTRL+SHIFT+R: enable global redirection ("gredirect.json")
|
||||||
|
- CTRL+R: disable global redirection
|
||||||
|
- ESC: remove focus. similar to vi normal mode.
|
||||||
|
- F1: Help
|
||||||
|
- F5: page refresh/reload
|
||||||
|
- F12: devtools
|
||||||
|
|
||||||
|
#### Address bar commands
|
||||||
|
- "/" for find-in-page
|
||||||
|
- ":" for address bar commands
|
||||||
|
- ac [bookmark/history path w/o ext] : load ".rec" file for autocomplete.
|
||||||
|
- b [bookmarkfilename w/o ext] : bookmark current page in file.
|
||||||
|
- bml [filename w/o extension]: load/execute the javascript file.
|
||||||
|
- cert : allow invalid certificates w/o arguments, otherwise restore to default.
|
||||||
|
- clear : the arguments could be
|
||||||
|
- cache : clear cache
|
||||||
|
- dns : clear dns cache
|
||||||
|
- storage: clear site storage data.
|
||||||
|
- {[options](https://www.electronjs.org/docs/latest/api/session#sescleardataoptions)}
|
||||||
|
- ext [extension path]: load unpacked Chrome extension.
|
||||||
|
- gr [gredirect index]: global redirection with corresponding index. Use the first global redirection url if no argument. Disable global redirection with any index out of the range.
|
||||||
|
- js [js code] : execute JS code at OS level. Note: "javascript:..." is special url and thus works in the current web page, while ":js ..." commands can do any OS operations.
|
||||||
|
- nc/uc : No Cookie forwarding/Use Cookie forwarding with global redirection.
|
||||||
|
- nh/uh for No/Use url history.
|
||||||
|
- nj/uj for No/Use external Javascript files.
|
||||||
|
- nr/ur for No/Use "redirect.json" for domain redirection.
|
||||||
|
- 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.
|
||||||
|
- 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].
|
||||||
|
|
||||||
|
#### Commands in no-focus mode (this mode is similar to vi Normal mode)
|
||||||
|
Pressing "ESC" to enter no-focus mode if not sure.
|
||||||
|
- ":" for address bar commands
|
||||||
|
- "/" for find-in-page with address bar
|
||||||
|
- "!" for "!" address bar commands
|
||||||
|
|
||||||
|
The other commands are defined in "mapkeys.json", which will map keys to address bar commands.
|
||||||
|
|
||||||
|
#### Configuration files
|
||||||
|
- "config": lines of address bar commands.
|
||||||
|
- "search.json": search engines as shortcut-queryUrl pairs.
|
||||||
|
- "default.autoc": predefined strings for address bar auto completion.
|
||||||
|
- "gredirect.json": global redirection urls as array of urls
|
||||||
|
- "redirect.json": domain-replacementDomain pairs, default to be applied.
|
||||||
|
- "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
|
||||||
|
|
||||||
|
#### Javascript at three levels
|
||||||
|
- Web page: urls like "javascript:" or bookmarklet command ":bml" run in web page.
|
||||||
|
- Browser (or renderer process) : "!xx" evaluates "xx.js", which could manipulate address bar etc.
|
||||||
|
- OS level (or main process) : ":js" to execute the following js code with all OS APIs available.
|
||||||
|
|
||||||
|
#### New usages
|
||||||
|
- Vector designing with web tech to replace Adobe Illustrator/Inkscape.
|
||||||
|
- Design with web tech.
|
||||||
|
|
||||||
|
- Printing to pdf with customized paper size.
|
||||||
|
- Magnify the pdf paper size to the required size.
|
||||||
|
|
||||||
|
OR
|
||||||
|
|
||||||
|
- Adjust window width and use addressbar command line ":Pdf {}" to export vector graphics.
|
||||||
|
- Use imageMagick to convert to any other vector graphics format.
|
||||||
|
|
||||||
|
#### License
|
||||||
|
You can copy or modify the code/program under the terms of the GPL3.0 or later versions.
|
|
@ -95,7 +95,6 @@ npm install ebrowser
|
||||||
<ul>
|
<ul>
|
||||||
<li>ac [bookmark/history path w/o ext] : load ".rec" file for autocomplete.</li>
|
<li>ac [bookmark/history path w/o ext] : load ".rec" file for autocomplete.</li>
|
||||||
<li>b [bookmarkfilename w/o ext] : bookmark current page in file.</li>
|
<li>b [bookmarkfilename w/o ext] : bookmark current page in file.</li>
|
||||||
<li>bjs : Browser-level JavaScript execution.</li>
|
|
||||||
<li>bml [filename w/o extension]: load/execute the javascript file.</li>
|
<li>bml [filename w/o extension]: load/execute the javascript file.</li>
|
||||||
<li>cert : allow invalid certificates w/o arguments, otherwise restore to default.</li>
|
<li>cert : allow invalid certificates w/o arguments, otherwise restore to default.</li>
|
||||||
<li>clear : the arguments could be
|
<li>clear : the arguments could be
|
||||||
|
@ -110,6 +109,8 @@ npm install ebrowser
|
||||||
<li>gr [gredirect index]: global redirection with corresponding index. Use the first global redirection url if no argument. Disable global redirection with any index out of the range.</li>
|
<li>gr [gredirect index]: global redirection with corresponding index. Use the first global redirection url if no argument. Disable global redirection with any index out of the range.</li>
|
||||||
<li>js [js code] : execute JS code at OS level. Note: "javascript:..." is special url and thus works in the current web page, while ":js ..." commands can do any OS operations.</li>
|
<li>js [js code] : execute JS code at OS level. Note: "javascript:..." is special url and thus works in the current web page, while ":js ..." commands can do any OS operations.</li>
|
||||||
<li>nc/uc : No Cookie forwarding/Use Cookie forwarding with global redirection.</li>
|
<li>nc/uc : No Cookie forwarding/Use Cookie forwarding with global redirection.</li>
|
||||||
|
<li>nh/uh for No/Use url history.</li>
|
||||||
|
<li>nj/uj for No/Use external Javascript files.</li>
|
||||||
<li>nr/ur for No/Use "redirect.json" for domain redirection.</li>
|
<li>nr/ur for No/Use "redirect.json" for domain redirection.</li>
|
||||||
<li>np : no proxy.</li>
|
<li>np : no proxy.</li>
|
||||||
<li>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".</li>
|
<li>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".</li>
|
||||||
|
@ -143,20 +144,9 @@ npm install ebrowser
|
||||||
<h4 id="javascript-at-three-levels">Javascript at three levels</h4>
|
<h4 id="javascript-at-three-levels">Javascript at three levels</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Web page: urls like "javascript:" or bookmarklet command ":bml" run in web page.</li>
|
<li>Web page: urls like "javascript:" or bookmarklet command ":bml" run in web page.</li>
|
||||||
<li>Browser (or renderer process) :
|
<li>Browser (or renderer process) : "!xx" evaluates "xx.js", which could manipulate address bar etc.</li>
|
||||||
<ul>
|
|
||||||
<li>":bjs" to execute the following js code at browser level.</li>
|
|
||||||
<li>"!xx" evaluates "xx.js", which could manipulate address bar etc.</li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li>OS level (or main process) : ":js" to execute the following js code with all OS APIs available.</li>
|
<li>OS level (or main process) : ":js" to execute the following js code with all OS APIs available.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h5 id="examples-for-jsbjs-commands">examples for ":js"/":bjs" commands</h5>
|
|
||||||
<pre><code>:js bJS=true //allow external Javascript files for web pages
|
|
||||||
:js bJS=false //disallow external Javascript files for web pages
|
|
||||||
:bjs bHistory=true //to record url history
|
|
||||||
:bjs bQueryHistory=true //to record query/command history
|
|
||||||
</code></pre>
|
|
||||||
<h4 id="new-usages">New usages</h4>
|
<h4 id="new-usages">New usages</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<description>Recent content on uweb browser: unlimited power</description>
|
<description>Recent content on uweb browser: unlimited power</description>
|
||||||
<generator>Hugo</generator>
|
<generator>Hugo</generator>
|
||||||
<language>en</language>
|
<language>en</language>
|
||||||
<lastBuildDate>Mon, 24 Jun 2024 19:36:44 +0800</lastBuildDate>
|
<lastBuildDate>Mon, 24 Jun 2024 10:28:02 +0800</lastBuildDate>
|
||||||
<atom:link href="/en/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="/en/index.xml" rel="self" type="application/rss+xml" />
|
||||||
<item>
|
<item>
|
||||||
<title>Text selection/processing</title>
|
<title>Text selection/processing</title>
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
/>
|
/>
|
||||||
</url><url>
|
</url><url>
|
||||||
<loc>/en/</loc>
|
<loc>/en/</loc>
|
||||||
<lastmod>2024-06-24T19:36:44+08:00</lastmod>
|
<lastmod>2024-06-24T10:28:02+08:00</lastmod>
|
||||||
<xhtml:link
|
<xhtml:link
|
||||||
rel="alternate"
|
rel="alternate"
|
||||||
hreflang="zh"
|
hreflang="zh"
|
||||||
|
@ -508,7 +508,7 @@
|
||||||
/>
|
/>
|
||||||
</url><url>
|
</url><url>
|
||||||
<loc>/en/ebrowserreadme/</loc>
|
<loc>/en/ebrowserreadme/</loc>
|
||||||
<lastmod>2024-06-24T19:36:44+08:00</lastmod>
|
<lastmod>2024-06-24T09:46:43+08:00</lastmod>
|
||||||
</url><url>
|
</url><url>
|
||||||
<loc>/en/mirrors/</loc>
|
<loc>/en/mirrors/</loc>
|
||||||
<lastmod>2024-06-18T23:17:17+08:00</lastmod>
|
<lastmod>2024-06-18T23:17:17+08:00</lastmod>
|
||||||
|
@ -539,7 +539,7 @@
|
||||||
/>
|
/>
|
||||||
</url><url>
|
</url><url>
|
||||||
<loc>/en/unlist/</loc>
|
<loc>/en/unlist/</loc>
|
||||||
<lastmod>2024-06-24T19:36:44+08:00</lastmod>
|
<lastmod>2024-06-24T10:28:02+08:00</lastmod>
|
||||||
<xhtml:link
|
<xhtml:link
|
||||||
rel="alternate"
|
rel="alternate"
|
||||||
hreflang="zh"
|
hreflang="zh"
|
||||||
|
|
|
@ -55,7 +55,6 @@ Mirror urls could be used like ":update https://uwebzh.netlify.app/misc/ebrowser
|
||||||
- ":" for address bar commands
|
- ":" for address bar commands
|
||||||
- ac [bookmark/history path w/o ext] : load ".rec" file for autocomplete.
|
- ac [bookmark/history path w/o ext] : load ".rec" file for autocomplete.
|
||||||
- b [bookmarkfilename w/o ext] : bookmark current page in file.
|
- b [bookmarkfilename w/o ext] : bookmark current page in file.
|
||||||
- bjs : Browser-level JavaScript execution.
|
|
||||||
- bml [filename w/o extension]: load/execute the javascript file.
|
- bml [filename w/o extension]: load/execute the javascript file.
|
||||||
- cert : allow invalid certificates w/o arguments, otherwise restore to default.
|
- cert : allow invalid certificates w/o arguments, otherwise restore to default.
|
||||||
- clear : the arguments could be
|
- clear : the arguments could be
|
||||||
|
@ -67,6 +66,8 @@ Mirror urls could be used like ":update https://uwebzh.netlify.app/misc/ebrowser
|
||||||
- gr [gredirect index]: global redirection with corresponding index. Use the first global redirection url if no argument. Disable global redirection with any index out of the range.
|
- gr [gredirect index]: global redirection with corresponding index. Use the first global redirection url if no argument. Disable global redirection with any index out of the range.
|
||||||
- js [js code] : execute JS code at OS level. Note: "javascript:..." is special url and thus works in the current web page, while ":js ..." commands can do any OS operations.
|
- js [js code] : execute JS code at OS level. Note: "javascript:..." is special url and thus works in the current web page, while ":js ..." commands can do any OS operations.
|
||||||
- nc/uc : No Cookie forwarding/Use Cookie forwarding with global redirection.
|
- nc/uc : No Cookie forwarding/Use Cookie forwarding with global redirection.
|
||||||
|
- nh/uh for No/Use url history.
|
||||||
|
- nj/uj for No/Use external Javascript files.
|
||||||
- nr/ur for No/Use "redirect.json" for domain redirection.
|
- nr/ur for No/Use "redirect.json" for domain redirection.
|
||||||
- np : no proxy.
|
- 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".
|
- 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".
|
||||||
|
@ -96,18 +97,9 @@ The other commands are defined in "mapkeys.json", which will map keys to address
|
||||||
|
|
||||||
#### Javascript at three levels
|
#### Javascript at three levels
|
||||||
- Web page: urls like "javascript:" or bookmarklet command ":bml" run in web page.
|
- Web page: urls like "javascript:" or bookmarklet command ":bml" run in web page.
|
||||||
- Browser (or renderer process) :
|
- Browser (or renderer process) : "!xx" evaluates "xx.js", which could manipulate address bar etc.
|
||||||
- ":bjs" to execute the following js code at browser level.
|
|
||||||
- "!xx" evaluates "xx.js", which could manipulate address bar etc.
|
|
||||||
- OS level (or main process) : ":js" to execute the following js code with all OS APIs available.
|
- OS level (or main process) : ":js" to execute the following js code with all OS APIs available.
|
||||||
|
|
||||||
##### examples for ":js"/":bjs" commands
|
|
||||||
|
|
||||||
:js bJS=true //allow external Javascript files for web pages
|
|
||||||
:js bJS=false //disallow external Javascript files for web pages
|
|
||||||
:bjs bHistory=true //to record url history
|
|
||||||
:bjs bQueryHistory=true //to record query/command history
|
|
||||||
|
|
||||||
#### New usages
|
#### New usages
|
||||||
- Vector designing with web tech to replace Adobe Illustrator/Inkscape.
|
- Vector designing with web tech to replace Adobe Illustrator/Inkscape.
|
||||||
- Design with web tech.
|
- Design with web tech.
|
||||||
|
|
|
@ -49,7 +49,6 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
}
|
}
|
||||||
.autocomplete-items div {
|
.autocomplete-items div {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #fff;
|
|
||||||
}
|
}
|
||||||
.autocomplete-items div:hover {
|
.autocomplete-items div:hover {
|
||||||
background-color: #e9e9e9;
|
background-color: #e9e9e9;
|
||||||
|
@ -66,13 +65,8 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
var closedUrls = [];
|
var closedUrls = [];
|
||||||
var autocStrArray = [];
|
var autocStrArray = [];
|
||||||
var defaultSE = "https://www.bing.com/search?q=%s";
|
var defaultSE = "https://www.bing.com/search?q=%s";
|
||||||
var historyFile = path.join(__dirname,'history.rec');
|
|
||||||
var bHistory = false;
|
|
||||||
var bQueryHistory = false;
|
var bQueryHistory = false;
|
||||||
var autocMode = 0; //0 for substring, 1 for startsWith
|
var autocMode = 0; //0 for substring, 1 for startsWith
|
||||||
const JSPREFIX_LOAD = "(async ()=>{let d=document;async function _loadJs(u){var a=d.createElement('script');a.type='text/javascript';a.async=false;a.src=u;d.body.appendChild(a);await new Promise(resolve=>a.onload=resolve)}";
|
|
||||||
const BML_md = JSPREFIX_LOAD + "await _loadJs('https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js');let b=d.body;b.innerHTML=marked.parse(b.textContent)})()";
|
|
||||||
|
|
||||||
let lastKeys;
|
let lastKeys;
|
||||||
let lastKeys_millis = 0;
|
let lastKeys_millis = 0;
|
||||||
|
|
||||||
|
@ -84,10 +78,7 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
initSearchEngines(jsonString,false);
|
initSearchEngines(jsonString,false);
|
||||||
});
|
});
|
||||||
fs.readFile(path.join(__dirname,'mapkeys.json'), 'utf8', (err, jsonStr) => {
|
fs.readFile(path.join(__dirname,'mapkeys.json'), 'utf8', (err, jsonStr) => {
|
||||||
if (err) {
|
if (err) return;
|
||||||
coloncommand(":js fetch2file(repositoryurl,'mapkeys.json')");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
mapKeys = JSON.parse(jsonStr);
|
mapKeys = JSON.parse(jsonStr);
|
||||||
}catch(e){}
|
}catch(e){}
|
||||||
|
@ -135,24 +126,9 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
iTab = i;
|
iTab = i;
|
||||||
tabs.children[iTab].classList.add('curWV');
|
tabs.children[iTab].classList.add('curWV');
|
||||||
}
|
}
|
||||||
function cbFinishLoad(e){
|
|
||||||
let tab = e.target;
|
|
||||||
let js = tab.dataset.jsonce;
|
|
||||||
if(js){
|
|
||||||
tab.dataset.jsonce = null;
|
|
||||||
tab.executeJavaScript(js,false);
|
|
||||||
}
|
|
||||||
if(!bHistory) return;
|
|
||||||
let histItem = tab.getTitle()+" "+tab.getURL()+"\n";
|
|
||||||
fs.appendFile(historyFile, histItem, (err) => {});
|
|
||||||
}
|
|
||||||
function initTab(tab){
|
|
||||||
tab.allowpopups = true;
|
|
||||||
tab.addEventListener('did-finish-load',cbFinishLoad);
|
|
||||||
}
|
|
||||||
function newTab(){
|
function newTab(){
|
||||||
var tab = document.createElement('webview');
|
var tab = document.createElement('webview');
|
||||||
initTab(tab);
|
tab.allowpopups = true;
|
||||||
tabs.appendChild(tab);
|
tabs.appendChild(tab);
|
||||||
}
|
}
|
||||||
function tabInc(num){
|
function tabInc(num){
|
||||||
|
@ -181,9 +157,6 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
tabs.children[iTab].classList.add('curWV');
|
tabs.children[iTab].classList.add('curWV');
|
||||||
return getWinTitle();
|
return getWinTitle();
|
||||||
}
|
}
|
||||||
function tabJS(js){
|
|
||||||
tabs.children[iTab].executeJavaScript(js,false);
|
|
||||||
}
|
|
||||||
function getWinTitle(){
|
function getWinTitle(){
|
||||||
let t=tabs.children[iTab];
|
let t=tabs.children[iTab];
|
||||||
let title = (iTab+1) + '/' + tabs.children.length;
|
let title = (iTab+1) + '/' + tabs.children.length;
|
||||||
|
@ -213,45 +186,33 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
if(e.ctrlKey){
|
if(e.ctrlKey){
|
||||||
switch(key){
|
switch(key){
|
||||||
case "Home":
|
case "Home":
|
||||||
tabJS("window.scrollTo(0,0)");
|
tabs.children[iTab].src = "javascript:window.scrollTo(0,0)";
|
||||||
return;
|
return;
|
||||||
case "End":
|
case "End":
|
||||||
tabJS("window.scrollTo(0,document.body.scrollHeight)");
|
tabs.children[iTab].src="javascript:window.scrollTo(0,document.body.scrollHeight)"
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SCROLL: do {
|
|
||||||
let h = -32;
|
|
||||||
switch(key){
|
switch(key){
|
||||||
case " ":
|
|
||||||
if(inputE === document.activeElement) return;
|
|
||||||
if(e.shiftKey){
|
|
||||||
h = -3*document.documentElement.clientHeight/4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "PageDown":
|
case "PageDown":
|
||||||
h = 3*document.documentElement.clientHeight/4;
|
tabs.children[iTab].src =
|
||||||
break;
|
"javascript:window.scrollBy(0,3*document.documentElement.clientHeight/4)";
|
||||||
|
return;
|
||||||
case "PageUp":
|
case "PageUp":
|
||||||
h = -3*document.documentElement.clientHeight/4;
|
tabs.children[iTab].src = "javascript:window.scrollBy(0,-3*document.documentElement.clientHeight/4)";
|
||||||
break;
|
return;
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
h = 32;
|
if(inputE !== document.activeElement || 0==inputE.nextElementSibling.children.length)
|
||||||
|
tabs.children[iTab].src="javascript:window.scrollBy(0,32)";
|
||||||
|
return;
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
if(inputE === document.activeElement &&
|
if(inputE !== document.activeElement || 0==inputE.nextElementSibling.children.length)
|
||||||
0!==inputE.nextElementSibling.children.length)
|
tabs.children[iTab].src="javascript:window.scrollBy(0,-32)";
|
||||||
return;
|
return;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break SCROLL;
|
|
||||||
}
|
}
|
||||||
let js = `javascript:window.scrollBy(0,${h})`;
|
|
||||||
tabJS(js);
|
|
||||||
return;
|
|
||||||
}while(false);
|
|
||||||
|
|
||||||
if(inputE === document.activeElement){
|
if(inputE === document.activeElement){
|
||||||
if (9===e.keyCode){//tab completion
|
if (9===e.keyCode){//tab completion
|
||||||
}
|
}
|
||||||
|
@ -308,9 +269,6 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
case "b":
|
case "b":
|
||||||
bookmark(args);
|
bookmark(args);
|
||||||
return;
|
return;
|
||||||
case "bjs":
|
|
||||||
eval(cmd.slice(5));
|
|
||||||
return;
|
|
||||||
case "bml":
|
case "bml":
|
||||||
bml(args);
|
bml(args);
|
||||||
return;
|
return;
|
||||||
|
@ -417,16 +375,15 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var url=q;
|
var url=q;
|
||||||
NOREC: do{
|
|
||||||
do {
|
do {
|
||||||
if(q.length>12){
|
if(q.length>12){
|
||||||
let c6 = q.charCodeAt(6);
|
let c6 = q.charCodeAt(6);
|
||||||
if(47===c6){// '/'
|
if(47===c6){// '/'
|
||||||
let c5 = q.charCodeAt(5);
|
let c5 = q.charCodeAt(5);
|
||||||
if(47===c5 && 58===q.charCodeAt(4))//http/file urls
|
if(47===c5 && 58===q.charCodeAt(4))//http/file urls
|
||||||
break NOREC;
|
break;
|
||||||
if(58===c5 && 47===q.charCodeAt(7))//https://
|
if(58===c5 && 47===q.charCodeAt(7))//https://
|
||||||
break NOREC;
|
break;
|
||||||
}else if(q.startsWith("javascript:")){
|
}else if(q.startsWith("javascript:")){
|
||||||
tabs.children[iTab].executeJavaScript(q.substring(11),false);
|
tabs.children[iTab].executeJavaScript(q.substring(11),false);
|
||||||
recQueryHistory(q);
|
recQueryHistory(q);
|
||||||
|
@ -441,14 +398,14 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
}
|
}
|
||||||
if(q.indexOf('.')>0){
|
if(q.indexOf('.')>0){
|
||||||
url = 'https://'+q;
|
url = 'https://'+q;
|
||||||
break NOREC;
|
break;
|
||||||
}
|
}
|
||||||
url = defaultSE.replace('%s',q);
|
url = defaultSE.replace('%s',q);
|
||||||
|
recQueryHistory(q);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
url = bang(q, iS);
|
url = bang(q, iS);
|
||||||
}while(false);
|
recQueryHistory(q);
|
||||||
recQueryHistory(q);
|
|
||||||
}while(false);
|
}while(false);
|
||||||
tabs.children[iTab].src=url;
|
tabs.children[iTab].src=url;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +501,6 @@ function autocomplete(inp,container,arr) {
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
tabs = document.body.children[1];
|
tabs = document.body.children[1];
|
||||||
initTab(tabs.children[0]);
|
|
||||||
{
|
{
|
||||||
let inp = document.forms[0].q;
|
let inp = document.forms[0].q;
|
||||||
autocomplete(inp,inp.nextElementSibling,autocStrArray);
|
autocomplete(inp,inp.nextElementSibling,autocStrArray);
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"al":"javascript:/*comments:test*/alert('test')",
|
|
||||||
"uj":":js bJS=true //Use javascript",
|
|
||||||
"nj":":js bJS=false //No javascript",
|
|
||||||
"uh":":bjs bHistory=bQueryHistory=true //record/Use history",
|
|
||||||
"nh":":bjs bHistory=bQueryHistory=false //No history",
|
|
||||||
"md":":bjs tabJS(BML_md)"
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
{"version":"1.0.34",
|
{"version":"1.0.31",
|
||||||
"name": "ebrowser",
|
"name": "ebrowser",
|
||||||
"description": "The keyboard-friendly minimal suckless web browser",
|
"description": "The keyboard-friendly minimal suckless web browser",
|
||||||
"main": "webview.js",
|
"main": "webview.js",
|
||||||
|
@ -6,8 +6,7 @@
|
||||||
"webview.js",
|
"webview.js",
|
||||||
"index.html",
|
"index.html",
|
||||||
"package.json",
|
"package.json",
|
||||||
"README.md",
|
"README.md"
|
||||||
"mapkeys.json"
|
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"release": "electron-builder"
|
"release": "electron-builder"
|
||||||
|
|
|
@ -39,6 +39,7 @@ var gredirect;
|
||||||
var redirects;
|
var redirects;
|
||||||
var bRedirect = true;
|
var bRedirect = true;
|
||||||
var bJS = true;
|
var bJS = true;
|
||||||
|
var bHistory = false;
|
||||||
var bForwardCookie = false;
|
var bForwardCookie = false;
|
||||||
var proxies = {};
|
var proxies = {};
|
||||||
var proxy;
|
var proxy;
|
||||||
|
@ -47,6 +48,7 @@ var defaultUA =
|
||||||
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" +
|
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/" +
|
||||||
process.versions.chrome +" Safari/537.36";
|
process.versions.chrome +" Safari/537.36";
|
||||||
app.userAgentFallback = defaultUA;
|
app.userAgentFallback = defaultUA;
|
||||||
|
var historyFile = path.join(__dirname,'history.rec');
|
||||||
|
|
||||||
fs.readFile(path.join(__dirname,'redirect.json'), 'utf8', (err, jsonString) => {
|
fs.readFile(path.join(__dirname,'redirect.json'), 'utf8', (err, jsonString) => {
|
||||||
if (err) return;
|
if (err) return;
|
||||||
|
@ -137,7 +139,7 @@ app.on ('web-contents-created', (event, contents) => {
|
||||||
//contents.on('focus', ()=>{cbFocus(contents)});
|
//contents.on('focus', ()=>{cbFocus(contents)});
|
||||||
//contents.on('blur',()=>{cbBlur()});
|
//contents.on('blur',()=>{cbBlur()});
|
||||||
contents.session.webRequest.onBeforeRequest(interceptRequest);
|
contents.session.webRequest.onBeforeRequest(interceptRequest);
|
||||||
//contents.on('did-finish-load',()=>{cbFinishLoad(contents)});
|
contents.on('did-finish-load',()=>{cbFinishLoad(contents)});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -192,7 +194,7 @@ function addrCommand(cmd){
|
||||||
else
|
else
|
||||||
gredirect_disable();
|
gredirect_disable();
|
||||||
return;
|
return;
|
||||||
case "js"://execute js
|
case "js"://exetute js
|
||||||
eval(cmd.slice(4));
|
eval(cmd.slice(4));
|
||||||
return;
|
return;
|
||||||
case "nc":
|
case "nc":
|
||||||
|
@ -206,6 +208,18 @@ function addrCommand(cmd){
|
||||||
}
|
}
|
||||||
forwardCookie();
|
forwardCookie();
|
||||||
return;
|
return;
|
||||||
|
case "nh":
|
||||||
|
bHistory = false;
|
||||||
|
win.webContents.executeJavaScript("bQueryHistory=false",false);
|
||||||
|
return;
|
||||||
|
case "uh":
|
||||||
|
bHistory = true;
|
||||||
|
win.webContents.executeJavaScript("bQueryHistory=true",false);
|
||||||
|
return;
|
||||||
|
case "nj":
|
||||||
|
bJS = false; return;
|
||||||
|
case "uj":
|
||||||
|
bJS = true; return;
|
||||||
case "np":
|
case "np":
|
||||||
session.defaultSession.setProxy ({mode:"direct"});
|
session.defaultSession.setProxy ({mode:"direct"});
|
||||||
bRedirect = true;
|
bRedirect = true;
|
||||||
|
@ -261,6 +275,12 @@ function cbConsoleMsg(e, level, msg, line, sourceid){
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cbFinishLoad(webContents){
|
||||||
|
if(!bHistory) return;
|
||||||
|
let histItem = webContents.getTitle()+" "+webContents.getURL()+"\n";
|
||||||
|
fs.appendFile(historyFile, histItem, (err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
function cbFocus(webContents){
|
function cbFocus(webContents){
|
||||||
let js = "if(focusMesg){let m=focusMesg;focusMesg=null;m}";
|
let js = "if(focusMesg){let m=focusMesg;focusMesg=null;m}";
|
||||||
win.webContents.executeJavaScript(js,false).then((r)=>{
|
win.webContents.executeJavaScript(js,false).then((r)=>{
|
||||||
|
@ -373,7 +393,7 @@ function topMenu(){
|
||||||
win.webContents.executeJavaScript(js,false)
|
win.webContents.executeJavaScript(js,false)
|
||||||
}},
|
}},
|
||||||
{ label: 'getURL', accelerator: 'Ctrl+G', click: ()=>{
|
{ label: 'getURL', accelerator: 'Ctrl+G', click: ()=>{
|
||||||
let js="{let q=document.forms[0].q;q.focus();q.value=tabs.children[iTab].getURL()}"
|
let js="{let q=document.forms[0].q;q.focus();q.value=tabs.children[iTab].src}"
|
||||||
win.webContents.executeJavaScript(js,false)
|
win.webContents.executeJavaScript(js,false)
|
||||||
}},
|
}},
|
||||||
{ label: 'Select', accelerator: 'Ctrl+L', click:()=>{
|
{ label: 'Select', accelerator: 'Ctrl+L', click:()=>{
|
||||||
|
@ -437,7 +457,7 @@ if(e)e.blur();try{tabs.children[iTab].stopFindInPage('clearSelection')}catch(er)
|
||||||
win.webContents.executeJavaScript(js,false);
|
win.webContents.executeJavaScript(js,false);
|
||||||
}},
|
}},
|
||||||
{ label: 'Reload', accelerator: 'F5', click: ()=>{
|
{ label: 'Reload', accelerator: 'F5', click: ()=>{
|
||||||
win.webContents.executeJavaScript("tabs.children[iTab].reloadIgnoringCache()",false);
|
win.webContents.executeJavaScript("tabs.children[iTab].reload()",false);
|
||||||
}},
|
}},
|
||||||
{ label: 'Devtools', accelerator: 'F12', click: ()=>{
|
{ label: 'Devtools', accelerator: 'F12', click: ()=>{
|
||||||
let js = "try{tabs.children[iTab].openDevTools()}catch(e){console.log(e)}";
|
let js = "try{tabs.children[iTab].openDevTools()}catch(e){console.log(e)}";
|
||||||
|
@ -592,7 +612,17 @@ async function writeFile(filename, str){
|
||||||
|
|
||||||
function help(){
|
function help(){
|
||||||
const readme = "README.md";
|
const readme = "README.md";
|
||||||
const htmlFN = path.join(__dirname,readme);
|
const htmlFN = path.join(__dirname,readme+".html");
|
||||||
let js=`{let t=tabs.children[iTab];t.dataset.jsonce=BML_md;t.src="file://${htmlFN}"}`;
|
if(!fs.existsSync(htmlFN)){
|
||||||
|
const readmeP = path.join(__dirname,readme);
|
||||||
|
try {
|
||||||
|
fs.copyFileSync(readmeP, htmlFN);
|
||||||
|
const postscript ="<script src='https://cdn.jsdelivr.net/npm/marked@12.0.2/marked.min.js'></script><script>var d=document;var b=d.body;var t=b.textContent;t=t.slice(0,t.length-253);b.innerHTML=marked.parse(t);d.title=d.title||b.firstElementChild.innerText.trim();</script>";
|
||||||
|
fs.appendFileSync(htmlFN,postscript);
|
||||||
|
}catch(e){
|
||||||
|
htmlFN = readmeP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let js=`tabs.children[iTab].src="file://${htmlFN}"`;
|
||||||
win.webContents.executeJavaScript(js,false)
|
win.webContents.executeJavaScript(js,false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<sitemap>
|
<sitemap>
|
||||||
<loc>/en/sitemap.xml</loc>
|
<loc>/en/sitemap.xml</loc>
|
||||||
|
|
||||||
<lastmod>2024-06-24T19:36:44+08:00</lastmod>
|
<lastmod>2024-06-24T10:28:02+08:00</lastmod>
|
||||||
|
|
||||||
</sitemap>
|
</sitemap>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue