diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2018-05-06 21:42:43 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-06 21:42:43 +0900 |
commit | 104a9666ff627b11ce7cf3a5bf096b1bc3437bc1 (patch) | |
tree | 4d995736429753d8c9d2892ef6195e6517777fc9 /src/background/shared/completions | |
parent | 828ac8cd84ddae9565be67f56e452a416b305c7a (diff) | |
parent | cf30ef0cd503b3b9dee882202d64ba9db9922ee3 (diff) |
Merge pull request #386 from ueokande/addon-enabled-indicator
Addon enabled indicator
Diffstat (limited to 'src/background/shared/completions')
-rw-r--r-- | src/background/shared/completions/histories.js | 83 | ||||
-rw-r--r-- | src/background/shared/completions/index.js | 84 | ||||
-rw-r--r-- | src/background/shared/completions/tabs.js | 10 |
3 files changed, 177 insertions, 0 deletions
diff --git a/src/background/shared/completions/histories.js b/src/background/shared/completions/histories.js new file mode 100644 index 0000000..a7d3d47 --- /dev/null +++ b/src/background/shared/completions/histories.js @@ -0,0 +1,83 @@ +const filterHttp = (items) => { + const httpsHosts = items + .filter(item => item[1].protocol === 'https:') + .map(item => item[1].host); + const httpsHostSet = new Set(httpsHosts); + return items.filter( + item => !(item[1].protocol === 'http:' && httpsHostSet.has(item[1].host)) + ); +}; + +const filterEmptyTitle = (items) => { + return items.filter(item => item[0].title && item[0].title !== ''); +}; + +const filterClosedPath = (items) => { + const allSimplePaths = items + .filter(item => item[1].hash === '' && item[1].search === '') + .map(item => item[1].origin + item[1].pathname); + const allSimplePathSet = new Set(allSimplePaths); + return items.filter( + item => !(item[1].hash === '' && item[1].search === '' && + (/\/$/).test(item[1].pathname) && + allSimplePathSet.has( + (item[1].origin + item[1].pathname).replace(/\/$/, '') + ) + ) + ); +}; + +const reduceByPathname = (items, min) => { + let hash = {}; + for (let item of items) { + let pathname = item[1].origin + item[1].pathname; + if (!hash[pathname]) { + hash[pathname] = item; + } else if (hash[pathname][1].href.length > item[1].href.length) { + hash[pathname] = item; + } + } + let filtered = Object.values(hash); + if (filtered.length < min) { + return items; + } + return filtered; +}; + +const reduceByOrigin = (items, min) => { + let hash = {}; + for (let item of items) { + let origin = item[1].origin; + if (!hash[origin]) { + hash[origin] = item; + } else if (hash[origin][1].href.length > item[1].href.length) { + hash[origin] = item; + } + } + let filtered = Object.values(hash); + if (filtered.length < min) { + return items; + } + return filtered; +}; + +const getCompletions = (keyword) => { + return browser.history.search({ + text: keyword, + startTime: 0, + }).then((historyItems) => { + return [historyItems.map(item => [item, new URL(item.url)])] + .map(filterEmptyTitle) + .map(filterHttp) + .map(filterClosedPath) + .map(items => reduceByPathname(items, 10)) + .map(items => reduceByOrigin(items, 10)) + .map(items => items + .sort((x, y) => x[0].visitCount < y[0].visitCount) + .slice(0, 10) + .map(item => item[0]) + )[0]; + }); +}; + +export { getCompletions }; diff --git a/src/background/shared/completions/index.js b/src/background/shared/completions/index.js new file mode 100644 index 0000000..73b7b27 --- /dev/null +++ b/src/background/shared/completions/index.js @@ -0,0 +1,84 @@ +import * as tabs from './tabs'; +import * as histories from './histories'; + +const getOpenCompletions = (command, keywords, searchConfig) => { + return histories.getCompletions(keywords).then((pages) => { + let historyItems = pages.map((page) => { + return { + caption: page.title, + content: command + ' ' + page.url, + url: page.url + }; + }); + let engineNames = Object.keys(searchConfig.engines); + let engineItems = engineNames.filter(name => name.startsWith(keywords)) + .map(name => ({ + caption: name, + content: command + ' ' + name + })); + + let completions = []; + if (engineItems.length > 0) { + completions.push({ + name: 'Search Engines', + items: engineItems + }); + } + if (historyItems.length > 0) { + completions.push({ + name: 'History', + items: historyItems + }); + } + return completions; + }); +}; + +const getCompletions = (line, settings) => { + let typedWords = line.trim().split(/ +/); + let typing = ''; + if (!line.endsWith(' ')) { + typing = typedWords.pop(); + } + + if (typedWords.length === 0) { + return Promise.resolve([]); + } + let name = typedWords.shift(); + let keywords = typedWords.concat(typing).join(' '); + + switch (name) { + case 'o': + case 'open': + case 't': + case 'tabopen': + case 'w': + case 'winopen': + return getOpenCompletions(name, keywords, settings.search); + case 'b': + case 'buffer': + return tabs.getCompletions(keywords).then((gotTabs) => { + let items = gotTabs.map((tab) => { + return { + caption: tab.title, + content: name + ' ' + tab.title, + url: tab.url, + icon: tab.favIconUrl + }; + }); + return [ + { + name: 'Buffers', + items: items + } + ]; + }); + } + return Promise.resolve([]); +}; + +const complete = (line, settings) => { + return getCompletions(line, settings); +}; + +export { complete }; diff --git a/src/background/shared/completions/tabs.js b/src/background/shared/completions/tabs.js new file mode 100644 index 0000000..5edddca --- /dev/null +++ b/src/background/shared/completions/tabs.js @@ -0,0 +1,10 @@ +const getCompletions = (keyword) => { + return browser.tabs.query({ currentWindow: true }).then((tabs) => { + let matched = tabs.filter((t) => { + return t.url.includes(keyword) || t.title && t.title.includes(keyword); + }); + return matched; + }); +}; + +export { getCompletions }; |