diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2020-05-02 17:25:56 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-02 17:25:56 +0900 |
commit | 5df0537bcf65a341e79852b1b30379c73318529c (patch) | |
tree | aee5efe52412855f620cb514a13a2c14373f27b7 /src/background/completion/impl | |
parent | 685f2b7b69218b06b5bb676069e35f79c5048c9b (diff) | |
parent | 75abd90ecb8201ad845b266f96220d8adfe19b2d (diff) |
Merge pull request #749 from ueokande/qa-0.28
QA 0.28
Diffstat (limited to 'src/background/completion/impl')
-rw-r--r-- | src/background/completion/impl/BookmarkRepositoryImpl.ts | 29 | ||||
-rw-r--r-- | src/background/completion/impl/HistoryRepositoryImpl.ts | 49 | ||||
-rw-r--r-- | src/background/completion/impl/PrefetchAndCache.ts | 37 | ||||
-rw-r--r-- | src/background/completion/impl/TabRepositoryImpl.ts | 30 | ||||
-rw-r--r-- | src/background/completion/impl/filters.ts | 45 |
5 files changed, 109 insertions, 81 deletions
diff --git a/src/background/completion/impl/BookmarkRepositoryImpl.ts b/src/background/completion/impl/BookmarkRepositoryImpl.ts index 3b80b93..2bc779d 100644 --- a/src/background/completion/impl/BookmarkRepositoryImpl.ts +++ b/src/background/completion/impl/BookmarkRepositoryImpl.ts @@ -1,5 +1,5 @@ -import BookmarkRepository, {BookmarkItem} from "../BookmarkRepository"; -import {HistoryItem} from "../HistoryRepository"; +import BookmarkRepository, { BookmarkItem } from "../BookmarkRepository"; +import { HistoryItem } from "../HistoryRepository"; import PrefetchAndCache from "./PrefetchAndCache"; const COMPLETION_ITEM_LIMIT = 10; @@ -8,7 +8,7 @@ export default class CachedBookmarkRepository implements BookmarkRepository { private bookmarkCache: PrefetchAndCache<BookmarkItem>; constructor() { - this.bookmarkCache = new PrefetchAndCache(this.getter, this.filter, 10,); + this.bookmarkCache = new PrefetchAndCache(this.getter, this.filter, 10); } queryBookmarks(query: string): Promise<BookmarkItem[]> { @@ -16,10 +16,10 @@ export default class CachedBookmarkRepository implements BookmarkRepository { } private async getter(query: string): Promise<BookmarkItem[]> { - const items = await browser.bookmarks.search({query}); + const items = await browser.bookmarks.search({ query }); return items - .filter(item => item.title && item.title.length > 0) - .filter(item => item.type === 'bookmark' && item.url) + .filter((item) => item.title && item.title.length > 0) + .filter((item) => item.type === "bookmark" && item.url) .filter((item) => { let url = undefined; try { @@ -27,20 +27,23 @@ export default class CachedBookmarkRepository implements BookmarkRepository { } catch (e) { return false; } - return url.protocol !== 'place:'; + return url.protocol !== "place:"; }) .slice(0, COMPLETION_ITEM_LIMIT) - .map(item => ({ + .map((item) => ({ title: item.title!!, url: item.url!!, })); } private filter(items: HistoryItem[], query: string) { - return items.filter(item => { - return query.split(' ').every(keyword => { - return item.title.toLowerCase().includes(keyword.toLowerCase()) || item.url!!.includes(keyword) + return items.filter((item) => { + return query.split(" ").every((keyword) => { + return ( + item.title.toLowerCase().includes(keyword.toLowerCase()) || + item.url!!.includes(keyword) + ); }); - }) - }; + }); + } } diff --git a/src/background/completion/impl/HistoryRepositoryImpl.ts b/src/background/completion/impl/HistoryRepositoryImpl.ts index cd55cd0..b1992a4 100644 --- a/src/background/completion/impl/HistoryRepositoryImpl.ts +++ b/src/background/completion/impl/HistoryRepositoryImpl.ts @@ -1,5 +1,5 @@ import * as filters from "./filters"; -import HistoryRepository, {HistoryItem} from "../HistoryRepository"; +import HistoryRepository, { HistoryItem } from "../HistoryRepository"; import PrefetchAndCache from "./PrefetchAndCache"; const COMPLETION_ITEM_LIMIT = 10; @@ -8,13 +8,17 @@ export default class CachedHistoryRepository implements HistoryRepository { private historyCache: PrefetchAndCache<browser.history.HistoryItem>; constructor() { - this.historyCache = new PrefetchAndCache(this.getter, this.filter, 10) + this.historyCache = new PrefetchAndCache(this.getter, this.filter, 10); } async queryHistories(keywords: string): Promise<HistoryItem[]> { const items = await this.historyCache.get(keywords); - const filterOrKeep = <T>(source: T[], filter: (items: T[]) => T[], min: number): T[] => { + const filterOrKeep = <T>( + source: T[], + filter: (items: T[]) => T[], + min: number + ): T[] => { const filtered = filter(source); if (filtered.length < min) { return source; @@ -23,17 +27,23 @@ export default class CachedHistoryRepository implements HistoryRepository { }; return [items] - .map(items => filterOrKeep(items, filters.filterByPathname, COMPLETION_ITEM_LIMIT)) - .map(items => filterOrKeep(items, filters.filterByOrigin, COMPLETION_ITEM_LIMIT))[0] - .sort((x, y) => Number(y.visitCount) - Number(x.visitCount)) - .slice(0, COMPLETION_ITEM_LIMIT) - .map(item => ({ - title: item.title!!, - url: item.url!!, - })); + .map((items) => + filterOrKeep(items, filters.filterByPathname, COMPLETION_ITEM_LIMIT) + ) + .map((items) => + filterOrKeep(items, filters.filterByOrigin, COMPLETION_ITEM_LIMIT) + )[0] + .sort((x, y) => Number(y.visitCount) - Number(x.visitCount)) + .slice(0, COMPLETION_ITEM_LIMIT) + .map((item) => ({ + title: item.title!!, + url: item.url!!, + })); } - private async getter (keywords: string): Promise<browser.history.HistoryItem[]> { + private async getter( + keywords: string + ): Promise<browser.history.HistoryItem[]> { const items = await browser.history.search({ text: keywords, startTime: 0, @@ -42,14 +52,17 @@ export default class CachedHistoryRepository implements HistoryRepository { return [items] .map(filters.filterBlankTitle) .map(filters.filterHttp) - .map(filters.filterByTailingSlash)[0] + .map(filters.filterByTailingSlash)[0]; } private filter(items: browser.history.HistoryItem[], query: string) { - return items.filter(item => { - return query.split(' ').every(keyword => { - return item.title!!.toLowerCase().includes(keyword.toLowerCase()) || item.url!!.includes(keyword) + return items.filter((item) => { + return query.split(" ").every((keyword) => { + return ( + item.title!!.toLowerCase().includes(keyword.toLowerCase()) || + item.url!!.includes(keyword) + ); }); - }) - }; + }); + } } diff --git a/src/background/completion/impl/PrefetchAndCache.ts b/src/background/completion/impl/PrefetchAndCache.ts index 3c074c2..d2889b0 100644 --- a/src/background/completion/impl/PrefetchAndCache.ts +++ b/src/background/completion/impl/PrefetchAndCache.ts @@ -5,14 +5,14 @@ const WHITESPACE = /\s/; // `shortKey` returns a shorten key to pre-fetch completions and store in the // cache. The shorten key is generated by the following rules: -// +// // 1. If the query contains a space in the middle: i.e. the query consists of // multiple words, the method removes the last word from the query, and // returns joined remaining words with space. -// +// // 2. If the query is a single word and it's an URL, the method returns a new // URL excluding search query with the upper path of the original URL. -// +// // 3. If the query is a single word and it's not an URL, the method returns a // word with the half-length of the original query. // @@ -29,11 +29,15 @@ const WHITESPACE = /\s/; // export const shortKey = (query: string): string => { if (WHITESPACE.test(query)) { - return query.split(WHITESPACE).filter(word => word.length > 0).slice(0, -1).join(' '); + return query + .split(WHITESPACE) + .filter((word) => word.length > 0) + .slice(0, -1) + .join(" "); } let url; try { - url = new URL(query) + url = new URL(query); } catch (e) { return query.slice(0, query.length / 2); } @@ -42,12 +46,12 @@ export const shortKey = (query: string): string => { // may be on typing or removing URLs such as "such as https://goog" return query.slice(0, query.length / 2); } - if (url.pathname.endsWith('/')) { + if (url.pathname.endsWith("/")) { // remove parameters and move to upper path - return new URL('..', url).href; + return new URL("..", url).href; } // remove parameters - return new URL('.', url).href; + return new URL(".", url).href; }; export default class PrefetchAndCache<T> { @@ -58,9 +62,8 @@ export default class PrefetchAndCache<T> { constructor( private getter: Getter<T>, private filter: Filter<T>, - private prefetchThrethold: number = 1, - ) { - } + private prefetchThrethold: number = 1 + ) {} async get(query: string): Promise<T[]> { query = query.trim(); @@ -79,7 +82,7 @@ export default class PrefetchAndCache<T> { private needToRefresh(query: string): boolean { if (!this.shortKey) { // no cache - return true + return true; } if (query.length < this.shortKey.length) { @@ -89,17 +92,17 @@ export default class PrefetchAndCache<T> { } if (!query.startsWith(this.shortKey)) { - // queyr: "hello_w" - // shorten: "hello_morning" - return true + // queyr: "hello_w" + // shorten: "hello_morning" + return true; } - if (query.slice(this.shortKey.length).includes(' ')) { + if (query.slice(this.shortKey.length).includes(" ")) { // queyr: "hello x" // shorten: "hello" return true; } - return false + return false; } } diff --git a/src/background/completion/impl/TabRepositoryImpl.ts b/src/background/completion/impl/TabRepositoryImpl.ts index adcaba7..5e33e5a 100644 --- a/src/background/completion/impl/TabRepositoryImpl.ts +++ b/src/background/completion/impl/TabRepositoryImpl.ts @@ -1,34 +1,34 @@ import TabRepository, { Tab } from "../TabRepository"; -const COMPLETION_ITEM_LIMIT = 10; - export default class TabRepositoryImpl implements TabRepository { async queryTabs(query: string, excludePinned: boolean): Promise<Tab[]> { const tabs = await browser.tabs.query({ currentWindow: true }); return tabs .filter((t) => { - return t.url && t.url.toLowerCase().includes(query.toLowerCase()) || - t.title && t.title.toLowerCase().includes(query.toLowerCase()); + return ( + (t.url && t.url.toLowerCase().includes(query.toLowerCase())) || + (t.title && t.title.toLowerCase().includes(query.toLowerCase())) + ); }) .filter((t) => { return !(excludePinned && t.pinned); }) - .filter(item => item.id && item.title && item.url) - .slice(0, COMPLETION_ITEM_LIMIT) + .filter((item) => item.id && item.title && item.url) .map(TabRepositoryImpl.toEntity); } async getAllTabs(excludePinned: boolean): Promise<Tab[]> { - if (excludePinned) { - return (await browser.tabs.query({ currentWindow: true, pinned: true })) - .map(TabRepositoryImpl.toEntity) - - } - return (await browser.tabs.query({ currentWindow: true })) - .map(TabRepositoryImpl.toEntity) + if (excludePinned) { + return ( + await browser.tabs.query({ currentWindow: true, pinned: true }) + ).map(TabRepositoryImpl.toEntity); + } + return (await browser.tabs.query({ currentWindow: true })).map( + TabRepositoryImpl.toEntity + ); } - private static toEntity(tab: browser.tabs.Tab,): Tab { + private static toEntity(tab: browser.tabs.Tab): Tab { return { id: tab.id!!, url: tab.url!!, @@ -36,6 +36,6 @@ export default class TabRepositoryImpl implements TabRepository { title: tab.title!!, faviconUrl: tab.favIconUrl, index: tab.index, - } + }; } } diff --git a/src/background/completion/impl/filters.ts b/src/background/completion/impl/filters.ts index 3aa56e4..523491d 100644 --- a/src/background/completion/impl/filters.ts +++ b/src/background/completion/impl/filters.ts @@ -1,32 +1,36 @@ type Item = browser.history.HistoryItem; const filterHttp = (items: Item[]): Item[] => { - const httpsHosts = items.map(x => new URL(x.url as string)) - .filter(x => x.protocol === 'https:') - .map(x => x.host); + const httpsHosts = items + .map((x) => new URL(x.url as string)) + .filter((x) => x.protocol === "https:") + .map((x) => x.host); const hostsSet = new Set(httpsHosts); return items.filter((item: Item) => { const url = new URL(item.url as string); - return url.protocol === 'https:' || !hostsSet.has(url.host); + return url.protocol === "https:" || !hostsSet.has(url.host); }); }; const filterBlankTitle = (items: Item[]): Item[] => { - return items.filter(item => item.title && item.title !== ''); + return items.filter((item) => item.title && item.title !== ""); }; const filterByTailingSlash = (items: Item[]): Item[] => { - const urls = items.map(item => new URL(item.url as string)); + const urls = items.map((item) => new URL(item.url as string)); const simplePaths = urls - .filter(url => url.hash === '' && url.search === '') - .map(url => url.origin + url.pathname); + .filter((url) => url.hash === "" && url.search === "") + .map((url) => url.origin + url.pathname); const pathsSet = new Set(simplePaths); return items.filter((item) => { const url = new URL(item.url as string); - if (url.hash !== '' || url.search !== '' || - url.pathname.slice(-1) !== '/') { + if ( + url.hash !== "" || + url.search !== "" || + url.pathname.slice(-1) !== "/" + ) { return true; } return !pathsSet.has(url.origin + url.pathname.slice(0, -1)); @@ -34,14 +38,15 @@ const filterByTailingSlash = (items: Item[]): Item[] => { }; const filterByPathname = (items: Item[]): Item[] => { - const hash: {[key: string]: Item} = {}; + const hash: { [key: string]: Item } = {}; for (const item of items) { const url = new URL(item.url as string); const pathname = url.origin + url.pathname; if (!hash[pathname]) { hash[pathname] = item; - } else if ((hash[pathname].url as string).length > - (item.url as string).length) { + } else if ( + (hash[pathname].url as string).length > (item.url as string).length + ) { hash[pathname] = item; } } @@ -49,13 +54,14 @@ const filterByPathname = (items: Item[]): Item[] => { }; const filterByOrigin = (items: Item[]): Item[] => { - const hash: {[key: string]: Item} = {}; + const hash: { [key: string]: Item } = {}; for (const item of items) { const origin = new URL(item.url as string).origin; if (!hash[origin]) { hash[origin] = item; - } else if ((hash[origin].url as string).length > - (item.url as string).length) { + } else if ( + (hash[origin].url as string).length > (item.url as string).length + ) { hash[origin] = item; } } @@ -63,6 +69,9 @@ const filterByOrigin = (items: Item[]): Item[] => { }; export { - filterHttp, filterBlankTitle, filterByTailingSlash, - filterByPathname, filterByOrigin + filterHttp, + filterBlankTitle, + filterByTailingSlash, + filterByPathname, + filterByOrigin, }; |