commit
						1fc44c783a
					
				
					 10 changed files with 70 additions and 15 deletions
				
			
		|  | @ -33,7 +33,8 @@ | ||||||
|     "tabs", |     "tabs", | ||||||
|     "clipboardRead", |     "clipboardRead", | ||||||
|     "notifications", |     "notifications", | ||||||
|     "bookmarks" |     "bookmarks", | ||||||
|  |     "browserSettings" | ||||||
|   ], |   ], | ||||||
|   "web_accessible_resources": [ |   "web_accessible_resources": [ | ||||||
|     "build/console.html", |     "build/console.html", | ||||||
|  |  | ||||||
|  | @ -37,6 +37,8 @@ export default class OperationController { | ||||||
|       return this.operationInteractor.duplicate(); |       return this.operationInteractor.duplicate(); | ||||||
|     case operations.PAGE_SOURCE: |     case operations.PAGE_SOURCE: | ||||||
|       return this.operationInteractor.openPageSource(); |       return this.operationInteractor.openPageSource(); | ||||||
|  |     case operations.PAGE_HOME: | ||||||
|  |       return this.operationInteractor.openHome(operation.newTab); | ||||||
|     case operations.ZOOM_IN: |     case operations.ZOOM_IN: | ||||||
|       return this.operationInteractor.zoomIn(); |       return this.operationInteractor.zoomIn(); | ||||||
|     case operations.ZOOM_OUT: |     case operations.ZOOM_OUT: | ||||||
|  |  | ||||||
|  | @ -120,6 +120,6 @@ export default class CommandIndicator { | ||||||
| 
 | 
 | ||||||
|   async urlOrSearch(keywords) { |   async urlOrSearch(keywords) { | ||||||
|     let settings = await this.settingRepository.get(); |     let settings = await this.settingRepository.get(); | ||||||
|     return urls.normalizeUrl(keywords, settings.search); |     return urls.searchUrl(keywords, settings.search); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| import TabPresenter from '../presenters/tab'; | import TabPresenter from '../presenters/tab'; | ||||||
| import ConsolePresenter from '../presenters/console'; | import ConsolePresenter from '../presenters/console'; | ||||||
|  | import * as urls from '../../shared/urls'; | ||||||
| 
 | 
 | ||||||
| const ZOOM_SETTINGS = [ | const ZOOM_SETTINGS = [ | ||||||
|   0.33, 0.50, 0.66, 0.75, 0.80, 0.90, 1.00, |   0.33, 0.50, 0.66, 0.75, 0.80, 0.90, 1.00, | ||||||
|  | @ -172,5 +173,17 @@ export default class OperationInteractor { | ||||||
|     let tab = await this.tabPresenter.getCurrent(); |     let tab = await this.tabPresenter.getCurrent(); | ||||||
|     return this.consolePresenter.hide(tab.id); |     return this.consolePresenter.hide(tab.id); | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   async openHome(newTab) { | ||||||
|  |     let tab = await this.tabPresenter.getCurrent(); | ||||||
|  |     let result = await browser.browserSettings.homepageOverride.get({}); | ||||||
|  |     let us = urls.homepageUrls(result.value); | ||||||
|  |     if (us.length === 1 && !newTab) { | ||||||
|  |       return this.tabPresenter.open(us[0], tab.id); | ||||||
|  |     } | ||||||
|  |     for (let u of us) { | ||||||
|  |       this.tabPresenter.create(u, { openerTabId: tab.id }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ const paste = (win, newTab, searchSettings) => { | ||||||
| 
 | 
 | ||||||
|   if (win.document.execCommand('paste')) { |   if (win.document.execCommand('paste')) { | ||||||
|     let value = textarea.textContent; |     let value = textarea.textContent; | ||||||
|     let url = urls.normalizeUrl(value, searchSettings); |     let url = urls.searchUrl(value, searchSettings); | ||||||
|     browser.runtime.sendMessage({ |     browser.runtime.sendMessage({ | ||||||
|       type: messages.OPEN_URL, |       type: messages.OPEN_URL, | ||||||
|       url, |       url, | ||||||
|  |  | ||||||
|  | @ -40,6 +40,8 @@ const KeyMapFields = [ | ||||||
|     ['navigate.parent', 'Go to parent directory'], |     ['navigate.parent', 'Go to parent directory'], | ||||||
|     ['navigate.root', 'Go to root directory'], |     ['navigate.root', 'Go to root directory'], | ||||||
|     ['page.source', 'Open page source'], |     ['page.source', 'Open page source'], | ||||||
|  |     ['page.home', 'Open start page to current tab'], | ||||||
|  |     ['page.home?{"newTab":true}', 'Open start page in new tab'], | ||||||
|     ['focus.input', 'Focus input'], |     ['focus.input', 'Focus input'], | ||||||
|   ], [ |   ], [ | ||||||
|     ['find.start', 'Start find mode'], |     ['find.start', 'Start find mode'], | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ export default { | ||||||
| 
 | 
 | ||||||
|   // Page
 |   // Page
 | ||||||
|   PAGE_SOURCE: 'page.source', |   PAGE_SOURCE: 'page.source', | ||||||
|  |   PAGE_HOME: 'page.home', | ||||||
| 
 | 
 | ||||||
|   // Tabs
 |   // Tabs
 | ||||||
|   TAB_CLOSE: 'tabs.close', |   TAB_CLOSE: 'tabs.close', | ||||||
|  |  | ||||||
|  | @ -52,6 +52,8 @@ export default { | ||||||
|     "gU": { "type": "navigate.root" }, |     "gU": { "type": "navigate.root" }, | ||||||
|     "gi": { "type": "focus.input" }, |     "gi": { "type": "focus.input" }, | ||||||
|     "gf": { "type": "page.source" }, |     "gf": { "type": "page.source" }, | ||||||
|  |     "gh": { "type": "page.home" }, | ||||||
|  |     "gH": { "type": "page.home", "newTab": true }, | ||||||
|     "y": { "type": "urls.yank" }, |     "y": { "type": "urls.yank" }, | ||||||
|     "p": { "type": "urls.paste", "newTab": false }, |     "p": { "type": "urls.paste", "newTab": false }, | ||||||
|     "P": { "type": "urls.paste", "newTab": true }, |     "P": { "type": "urls.paste", "newTab": true }, | ||||||
|  |  | ||||||
|  | @ -3,9 +3,9 @@ const trimStart = (str) => { | ||||||
|   return str.replace(/^\s+/, ''); |   return str.replace(/^\s+/, ''); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:']; | const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:', 'about:']; | ||||||
| 
 | 
 | ||||||
| const normalizeUrl = (keywords, searchSettings) => { | const searchUrl = (keywords, searchSettings) => { | ||||||
|   try { |   try { | ||||||
|     let u = new URL(keywords); |     let u = new URL(keywords); | ||||||
|     if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { |     if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { | ||||||
|  | @ -28,4 +28,20 @@ const normalizeUrl = (keywords, searchSettings) => { | ||||||
|   return template.replace('{}', encodeURIComponent(query)); |   return template.replace('{}', encodeURIComponent(query)); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export { normalizeUrl }; | const normalizeUrl = (url) => { | ||||||
|  |   try { | ||||||
|  |     let u = new URL(url); | ||||||
|  |     if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { | ||||||
|  |       return u.href; | ||||||
|  |     } | ||||||
|  |   } catch (e) { | ||||||
|  |     // fallthrough
 | ||||||
|  |   } | ||||||
|  |   return 'http://' + url; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const homepageUrls = (value) => { | ||||||
|  |   return value.split('|').map(normalizeUrl); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export { searchUrl, normalizeUrl, homepageUrls }; | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| import * as parsers from 'shared/urls'; | import * as parsers from 'shared/urls'; | ||||||
| 
 | 
 | ||||||
| describe("shared/commands/parsers", () => { | describe("shared/commands/parsers", () => { | ||||||
|   describe('#normalizeUrl', () => { |   describe('#searchUrl', () => { | ||||||
|     const config = { |     const config = { | ||||||
|       default: 'google', |       default: 'google', | ||||||
|       engines: { |       engines: { | ||||||
|  | @ -11,29 +11,47 @@ describe("shared/commands/parsers", () => { | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     it('convertes search url', () => { |     it('convertes search url', () => { | ||||||
|       expect(parsers.normalizeUrl('google.com', config)) |       expect(parsers.searchUrl('google.com', config)) | ||||||
|         .to.equal('http://google.com'); |         .to.equal('http://google.com'); | ||||||
|       expect(parsers.normalizeUrl('google apple', config)) |       expect(parsers.searchUrl('google apple', config)) | ||||||
|         .to.equal('https://google.com/search?q=apple'); |         .to.equal('https://google.com/search?q=apple'); | ||||||
|       expect(parsers.normalizeUrl('yahoo apple', config)) |       expect(parsers.searchUrl('yahoo apple', config)) | ||||||
|         .to.equal('https://yahoo.com/search?q=apple'); |         .to.equal('https://yahoo.com/search?q=apple'); | ||||||
|       expect(parsers.normalizeUrl('google apple banana', config)) |       expect(parsers.searchUrl('google apple banana', config)) | ||||||
|         .to.equal('https://google.com/search?q=apple%20banana'); |         .to.equal('https://google.com/search?q=apple%20banana'); | ||||||
|       expect(parsers.normalizeUrl('yahoo C++CLI', config)) |       expect(parsers.searchUrl('yahoo C++CLI', config)) | ||||||
|         .to.equal('https://yahoo.com/search?q=C%2B%2BCLI'); |         .to.equal('https://yahoo.com/search?q=C%2B%2BCLI'); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('user default  search engine', () => { |     it('user default  search engine', () => { | ||||||
|       expect(parsers.normalizeUrl('apple banana', config)) |       expect(parsers.searchUrl('apple banana', config)) | ||||||
|         .to.equal('https://google.com/search?q=apple%20banana'); |         .to.equal('https://google.com/search?q=apple%20banana'); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     it('searches with a word containing a colon', () => { |     it('searches with a word containing a colon', () => { | ||||||
|       expect(parsers.normalizeUrl('foo:', config)) |       expect(parsers.searchUrl('foo:', config)) | ||||||
|         .to.equal('https://google.com/search?q=foo%3A'); |         .to.equal('https://google.com/search?q=foo%3A'); | ||||||
|       expect(parsers.normalizeUrl('std::vector', config)) |       expect(parsers.searchUrl('std::vector', config)) | ||||||
|         .to.equal('https://google.com/search?q=std%3A%3Avector'); |         .to.equal('https://google.com/search?q=std%3A%3Avector'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  | 
 | ||||||
|  |   describe('#normalizeUrl', () => { | ||||||
|  |     it('normalize urls', () => { | ||||||
|  |       expect(parsers.normalizeUrl('https://google.com/')) | ||||||
|  |         .to.equal('https://google.com/'); | ||||||
|  |       expect(parsers.normalizeUrl('google.com')) | ||||||
|  |         .to.equal('http://google.com'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('#homepageUrls', () => { | ||||||
|  |     it('split urls', () => { | ||||||
|  |       expect(parsers.homepageUrls('https://google.com/')) | ||||||
|  |         .to.deep.equal(['https://google.com/']); | ||||||
|  |       expect(parsers.homepageUrls('yahoo.com|https://i-beam.org/')) | ||||||
|  |         .to.deep.equal(['http://yahoo.com', 'https://i-beam.org/']); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Reference in a new issue