From 1f89464e4285936bdd509e2607aa70e93d5383a4 Mon Sep 17 00:00:00 2001 From: Shin'ya Ueoka Date: Sun, 9 Dec 2018 10:19:08 +0900 Subject: [PATCH] Add gh/gH to open home page --- src/background/controllers/operation.js | 2 ++ src/background/usecases/command.js | 2 +- src/background/usecases/operation.js | 13 +++++++++ src/content/urls.js | 2 +- src/shared/operations.js | 1 + src/shared/settings/default.js | 2 ++ src/shared/urls.js | 20 ++++++++++++-- test/shared/urls.test.js | 36 ++++++++++++++++++------- 8 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/background/controllers/operation.js b/src/background/controllers/operation.js index 1339006..aea85fc 100644 --- a/src/background/controllers/operation.js +++ b/src/background/controllers/operation.js @@ -37,6 +37,8 @@ export default class OperationController { return this.operationInteractor.duplicate(); case operations.PAGE_SOURCE: return this.operationInteractor.openPageSource(); + case operations.PAGE_HOME: + return this.operationInteractor.openHome(operation.newTab); case operations.ZOOM_IN: return this.operationInteractor.zoomIn(); case operations.ZOOM_OUT: diff --git a/src/background/usecases/command.js b/src/background/usecases/command.js index f6ade43..0d21041 100644 --- a/src/background/usecases/command.js +++ b/src/background/usecases/command.js @@ -120,6 +120,6 @@ export default class CommandIndicator { async urlOrSearch(keywords) { let settings = await this.settingRepository.get(); - return urls.normalizeUrl(keywords, settings.search); + return urls.searchUrl(keywords, settings.search); } } diff --git a/src/background/usecases/operation.js b/src/background/usecases/operation.js index 74ea830..bf905be 100644 --- a/src/background/usecases/operation.js +++ b/src/background/usecases/operation.js @@ -1,5 +1,6 @@ import TabPresenter from '../presenters/tab'; import ConsolePresenter from '../presenters/console'; +import * as urls from '../../shared/urls'; const ZOOM_SETTINGS = [ 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(); 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 }); + } + } } diff --git a/src/content/urls.js b/src/content/urls.js index 1c5b7e5..6e7ea31 100644 --- a/src/content/urls.js +++ b/src/content/urls.js @@ -26,7 +26,7 @@ const paste = (win, newTab, searchSettings) => { if (win.document.execCommand('paste')) { let value = textarea.textContent; - let url = urls.normalizeUrl(value, searchSettings); + let url = urls.searchUrl(value, searchSettings); browser.runtime.sendMessage({ type: messages.OPEN_URL, url, diff --git a/src/shared/operations.js b/src/shared/operations.js index 778b1cf..026f97c 100644 --- a/src/shared/operations.js +++ b/src/shared/operations.js @@ -40,6 +40,7 @@ export default { // Page PAGE_SOURCE: 'page.source', + PAGE_HOME: 'page.home', // Tabs TAB_CLOSE: 'tabs.close', diff --git a/src/shared/settings/default.js b/src/shared/settings/default.js index 4163064..5b0950e 100644 --- a/src/shared/settings/default.js +++ b/src/shared/settings/default.js @@ -52,6 +52,8 @@ export default { "gU": { "type": "navigate.root" }, "gi": { "type": "focus.input" }, "gf": { "type": "page.source" }, + "gh": { "type": "page.home" }, + "gH": { "type": "page.home", "newTab": true }, "y": { "type": "urls.yank" }, "p": { "type": "urls.paste", "newTab": false }, "P": { "type": "urls.paste", "newTab": true }, diff --git a/src/shared/urls.js b/src/shared/urls.js index d6c31e6..efdbcdb 100644 --- a/src/shared/urls.js +++ b/src/shared/urls.js @@ -5,7 +5,7 @@ const trimStart = (str) => { const SUPPORTED_PROTOCOLS = ['http:', 'https:', 'ftp:', 'mailto:']; -const normalizeUrl = (keywords, searchSettings) => { +const searchUrl = (keywords, searchSettings) => { try { let u = new URL(keywords); if (SUPPORTED_PROTOCOLS.includes(u.protocol.toLowerCase())) { @@ -28,4 +28,20 @@ const normalizeUrl = (keywords, searchSettings) => { 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 }; diff --git a/test/shared/urls.test.js b/test/shared/urls.test.js index 5c5e1a9..f004b3d 100644 --- a/test/shared/urls.test.js +++ b/test/shared/urls.test.js @@ -1,7 +1,7 @@ import * as parsers from 'shared/urls'; describe("shared/commands/parsers", () => { - describe('#normalizeUrl', () => { + describe('#searchUrl', () => { const config = { default: 'google', engines: { @@ -11,29 +11,47 @@ describe("shared/commands/parsers", () => { }; it('convertes search url', () => { - expect(parsers.normalizeUrl('google.com', config)) + expect(parsers.searchUrl('google.com', config)) .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'); - expect(parsers.normalizeUrl('yahoo apple', config)) + expect(parsers.searchUrl('yahoo apple', config)) .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'); - expect(parsers.normalizeUrl('yahoo C++CLI', config)) + expect(parsers.searchUrl('yahoo C++CLI', config)) .to.equal('https://yahoo.com/search?q=C%2B%2BCLI'); }); 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'); }); 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'); - expect(parsers.normalizeUrl('std::vector', config)) + expect(parsers.searchUrl('std::vector', config)) .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/']); + }); + }); });