new links, style tweaks & new configs
This commit is contained in:
+251
-160
@@ -16,36 +16,71 @@
|
|||||||
color: '#000',
|
color: '#000',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Work',
|
category: 'Google',
|
||||||
|
name: 'Mail',
|
||||||
|
key: 'm',
|
||||||
|
url: 'https://mail.google.com/mail/u/0/#inbox',
|
||||||
|
search: '/mail/u/0/?q={}#search/{}',
|
||||||
|
color: 'linear-gradient(135deg, #4285f4, #4249f4)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Google',
|
||||||
name: 'Drive',
|
name: 'Drive',
|
||||||
key: 'd',
|
key: 'd',
|
||||||
url: 'https://drive.google.com',
|
url: 'https://drive.google.com/drive/u/0/my-drive',
|
||||||
search: '/drive/search?q={}',
|
search: '/drive/search?q={}',
|
||||||
color: 'linear-gradient(135deg, #4285f4, #4259f4)',
|
color: 'linear-gradient(135deg, #34a853, #345253)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Work',
|
category: 'Google',
|
||||||
name: 'GitHub',
|
|
||||||
key: 'g',
|
|
||||||
url: 'https://github.com',
|
|
||||||
search: '/search?q={}',
|
|
||||||
color: 'linear-gradient(135deg, #8ccae1, #6dabd6)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Work',
|
|
||||||
name: 'Keep',
|
name: 'Keep',
|
||||||
key: 'k',
|
key: 'k',
|
||||||
url: 'https://keep.google.com',
|
url: 'https://keep.google.com/u/0/',
|
||||||
search: '/#search/text={}',
|
search: '/#search/text={}',
|
||||||
color: 'linear-gradient(135deg, #fca550, #fcd050)',
|
color: 'linear-gradient(135deg, #fca550, #fcd050)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Lurk',
|
category: 'Work',
|
||||||
name: 'Hunt',
|
name: 'Slack',
|
||||||
key: 'p',
|
key: 'ss',
|
||||||
url: 'https://www.producthunt.com',
|
url: 'https://app.slack.com/client/T7K3RFA1M/all-dms',
|
||||||
|
color: 'linear-gradient(135deg, #6ecadc, #6e7adc)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Work',
|
||||||
|
name: 'AND.CO',
|
||||||
|
key: '.',
|
||||||
|
url: 'https://app.and.co/timers',
|
||||||
|
color: 'linear-gradient(135deg, #17d3aa, #1773aa)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Work',
|
||||||
|
name: 'Asana',
|
||||||
|
key: 'sa',
|
||||||
|
url: 'https://app.asana.com/0/inbox/490539250066176',
|
||||||
|
color: 'linear-gradient(135deg, #3be8b0, #1aafd0)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Code',
|
||||||
|
name: 'AWS',
|
||||||
|
key: 'a',
|
||||||
|
url: 'https://console.aws.amazon.com',
|
||||||
|
color: 'linear-gradient(135deg, #ff9900, #ff6400)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Code',
|
||||||
|
name: 'GitHub',
|
||||||
|
key: 'g',
|
||||||
|
url: 'https://github.com',
|
||||||
search: '/search?q={}',
|
search: '/search?q={}',
|
||||||
color: 'linear-gradient(135deg, #da552f, #da802f)',
|
color: 'linear-gradient(135deg, #8ccae1, #6d8bd6)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Code',
|
||||||
|
name: 'Local',
|
||||||
|
key: '0',
|
||||||
|
url: 'http://localhost:3000',
|
||||||
|
search: ':{}',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Lurk',
|
category: 'Lurk',
|
||||||
@@ -53,13 +88,21 @@
|
|||||||
key: 'r',
|
key: 'r',
|
||||||
url: 'https://www.reddit.com',
|
url: 'https://www.reddit.com',
|
||||||
search: '/search?q={}',
|
search: '/search?q={}',
|
||||||
color: 'linear-gradient(135deg, #5f99cf, #5f7dcf)',
|
color: 'linear-gradient(135deg, #5f99cf, #5f3dcf)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Lurk',
|
||||||
|
name: 'ProductHunt',
|
||||||
|
key: 'p',
|
||||||
|
url: 'https://www.producthunt.com',
|
||||||
|
search: '/search?q={}',
|
||||||
|
color: 'linear-gradient(135deg, #da552f, #da802f)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Lurk',
|
category: 'Lurk',
|
||||||
name: 'Unsplash',
|
name: 'Unsplash',
|
||||||
key: 'u',
|
key: 'u',
|
||||||
url: 'https://unsplash.com/new',
|
url: 'https://unsplash.com/images',
|
||||||
search: '/search/{}',
|
search: '/search/{}',
|
||||||
color: '#000',
|
color: '#000',
|
||||||
},
|
},
|
||||||
@@ -69,12 +112,12 @@
|
|||||||
key: 'h',
|
key: 'h',
|
||||||
url: 'https://hypem.com/popular',
|
url: 'https://hypem.com/popular',
|
||||||
search: '/search/{}',
|
search: '/search/{}',
|
||||||
color: 'linear-gradient(135deg, #83c441, #62c441)',
|
color: 'linear-gradient(135deg, #83c441, #628441)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Listen',
|
category: 'Listen',
|
||||||
name: 'SoundCloud',
|
name: 'SoundCloud',
|
||||||
key: 'S',
|
key: 'o',
|
||||||
url: 'https://soundcloud.com/discover',
|
url: 'https://soundcloud.com/discover',
|
||||||
search: '/search?q={}',
|
search: '/search?q={}',
|
||||||
color: 'linear-gradient(135deg, #ff8800, #ffc800)',
|
color: 'linear-gradient(135deg, #ff8800, #ffc800)',
|
||||||
@@ -85,7 +128,7 @@
|
|||||||
key: 's',
|
key: 's',
|
||||||
url: 'https://open.spotify.com',
|
url: 'https://open.spotify.com',
|
||||||
search: '/search/{}',
|
search: '/search/{}',
|
||||||
color: 'linear-gradient(135deg, #1DB954, #1Da974)',
|
color: 'linear-gradient(135deg, #1DB954, #1D7974)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Watch',
|
category: 'Watch',
|
||||||
@@ -93,14 +136,7 @@
|
|||||||
key: 'n',
|
key: 'n',
|
||||||
url: 'https://www.netflix.com/browse',
|
url: 'https://www.netflix.com/browse',
|
||||||
search: '/search?q={}',
|
search: '/search?q={}',
|
||||||
color: 'linear-gradient(135deg, #e50914, #e53509)',
|
color: 'linear-gradient(135deg, #e50914, #b50009)',
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Watch',
|
|
||||||
name: 'Twitch',
|
|
||||||
key: 't',
|
|
||||||
url: 'https://www.twitch.tv/directory/following',
|
|
||||||
color: 'linear-gradient(135deg, #6441a5, #7d41a5)',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Watch',
|
category: 'Watch',
|
||||||
@@ -108,23 +144,14 @@
|
|||||||
key: 'y',
|
key: 'y',
|
||||||
url: 'https://youtube.com/feed/subscriptions',
|
url: 'https://youtube.com/feed/subscriptions',
|
||||||
search: '/results?search_query={}',
|
search: '/results?search_query={}',
|
||||||
color: 'linear-gradient(135deg, #cd201f, #cd4c1f)',
|
color: 'linear-gradient(135deg, #cd201f, #8d1c1f)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Learn',
|
category: 'Watch',
|
||||||
name: 'Academy',
|
name: 'Twitch',
|
||||||
key: 'a',
|
key: 't',
|
||||||
url: 'https://www.khanacademy.org',
|
url: 'https://www.twitch.tv/directory/following',
|
||||||
search: '/search?page_search_query={}',
|
color: 'linear-gradient(135deg, #6441a5, #7d11a5)',
|
||||||
color: 'linear-gradient(135deg, #9cb443, #80b443)',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
category: 'Learn',
|
|
||||||
name: 'Coursera',
|
|
||||||
key: 'c',
|
|
||||||
url: 'https://www.coursera.org',
|
|
||||||
search: '/courses?query={}',
|
|
||||||
color: 'linear-gradient(135deg, #407ED7, #4058d7)',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
category: 'Learn',
|
category: 'Learn',
|
||||||
@@ -134,14 +161,38 @@
|
|||||||
search: '/search?q={}',
|
search: '/search?q={}',
|
||||||
color: 'linear-gradient(135deg, #171C23, #171923)',
|
color: 'linear-gradient(135deg, #171C23, #171923)',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
category: 'Learn',
|
||||||
|
name: 'Coursera',
|
||||||
|
key: 'c',
|
||||||
|
url: 'https://www.coursera.org',
|
||||||
|
search: '/courses?query={}',
|
||||||
|
color: 'linear-gradient(135deg, #407ED7, #4038d7)',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
category: 'Learn',
|
||||||
|
name: 'Khan',
|
||||||
|
key: 'K',
|
||||||
|
url: 'https://www.khanacademy.org',
|
||||||
|
search: '/search?page_search_query={}',
|
||||||
|
color: 'linear-gradient(135deg, #9cb443, #808443)',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
category: 'Download',
|
category: 'Download',
|
||||||
name: 'Bay',
|
name: 'TPB',
|
||||||
key: 'b',
|
key: 'B',
|
||||||
url: 'https://thepiratebay.org',
|
url: 'https://thepiratebay.org',
|
||||||
search: '/search/{}',
|
search: '/search/{}',
|
||||||
color: 'linear-gradient(135deg, #d2b9a6, #d2c4a6)',
|
color: 'linear-gradient(135deg, #d2b9a6, #d2c4a6)',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
category: 'Download',
|
||||||
|
name: 'RARBG',
|
||||||
|
key: 'R',
|
||||||
|
url: 'https://rarbg.to/torrents.php',
|
||||||
|
search: '/torrents.php?search=test',
|
||||||
|
color: 'linear-gradient(135deg, #3870bb, #386ebb)',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
category: 'Download',
|
category: 'Download',
|
||||||
name: 'YTS',
|
name: 'YTS',
|
||||||
@@ -150,14 +201,6 @@
|
|||||||
search: '/browse-movies/{}',
|
search: '/browse-movies/{}',
|
||||||
color: 'linear-gradient(135deg, #2f2f2f, #373737)',
|
color: 'linear-gradient(135deg, #2f2f2f, #373737)',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
category: 'Download',
|
|
||||||
name: '7digital',
|
|
||||||
key: '7',
|
|
||||||
url: 'https://us.7digital.com',
|
|
||||||
search: '/search?q={}',
|
|
||||||
color: 'linear-gradient(135deg, #07606e, #07466e)',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,23 +213,35 @@
|
|||||||
* The order and limit for each suggestion influencer. An "influencer" is
|
* The order and limit for each suggestion influencer. An "influencer" is
|
||||||
* just a suggestion source. The following influencers are available:
|
* just a suggestion source. The following influencers are available:
|
||||||
*
|
*
|
||||||
* - "Default" suggestions come from CONFIG.defaultSuggestions
|
* - "Default" suggestions come from CONFIG.defaultSuggestions (sync)
|
||||||
* - "DuckDuckGo" suggestions come from the duck duck go search api
|
* - "History" suggestions come from your previously entered queries (sync)
|
||||||
* - "History" suggestions come from your previously entered queries
|
* - "DuckDuckGo" suggestions come from the duck duck go search api (async)
|
||||||
*/
|
*/
|
||||||
influencers: [
|
influencers: [
|
||||||
{ name: 'Default', limit: 4 },
|
{ name: 'Default', limit: 4 },
|
||||||
{ name: 'History', limit: 1 },
|
|
||||||
{ name: 'DuckDuckGo', limit: 4 },
|
{ name: 'DuckDuckGo', limit: 4 },
|
||||||
],
|
],
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, suggestions aren't updated until all async influencers resolve.
|
||||||
|
* If false, synchronous suggestions display immediately, and async
|
||||||
|
* suggestions are appended. This is useful on high-latency networks.
|
||||||
|
*/
|
||||||
|
asyncInfluencersAreBlocking: false,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default search suggestions for the specified queries.
|
* Default search suggestions for the specified queries.
|
||||||
*/
|
*/
|
||||||
defaultSuggestions: {
|
defaultSuggestions: {
|
||||||
g: ['g/issues', 'g/pulls', 'gist.github.com'],
|
'.': ['./inout/in/invoices/create'],
|
||||||
r: ['r/r/unixporn', 'r/r/startpages'],
|
0: ['0:8000', '0:8080'],
|
||||||
S: ['S/you/likes', 'S/discover/the-upload'],
|
d: ['d/drive/u/1/my-drive', 'd/drive/u/2/my-drive'],
|
||||||
|
g: ['g/ossu'],
|
||||||
|
k: ['k/u/1/', 'k/u/2/'],
|
||||||
|
m: ['m/mail/u/1/#inbox', 'm/mail/u/2/#inbox'],
|
||||||
|
o: ['o/you/likes', 'o/discover/the-upload'],
|
||||||
|
r: ['r/r/startpages', 'r/r/listentothis'],
|
||||||
|
ss: ['ss/client/T018S4TL7CP/all-dms'],
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -337,12 +392,14 @@
|
|||||||
|
|
||||||
.center {
|
.center {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.center > * {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
@@ -355,10 +412,8 @@
|
|||||||
|
|
||||||
.clock {
|
.clock {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: -0.06rem;
|
|
||||||
font-size: 4rem;
|
font-size: 4rem;
|
||||||
font-weight: var(--font-weight-normal);
|
font-weight: var(--font-weight-normal);
|
||||||
text-align: center;
|
|
||||||
letter-spacing: 0.05rem;
|
letter-spacing: 0.05rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -422,11 +477,12 @@
|
|||||||
content: ' ';
|
content: ' ';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0.1rem;
|
bottom: 3px;
|
||||||
|
border-radius: 0.1em;
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 4px;
|
height: 2px;
|
||||||
background: var(--searchForeground);
|
background: var(--searchForeground);
|
||||||
opacity: 0.4;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-suggestion.highlight b::after {
|
.search-suggestion.highlight b::after {
|
||||||
@@ -434,8 +490,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
display: block;
|
padding: 3rem;
|
||||||
padding: 8vw;
|
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
@@ -454,6 +509,7 @@
|
|||||||
.command a {
|
.command a {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
margin: 1rem 0;
|
margin: 1rem 0;
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -535,11 +591,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1000px) {
|
@media (min-width: 1000px) {
|
||||||
.help {
|
|
||||||
display: flex;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-input {
|
.search-input {
|
||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
}
|
}
|
||||||
@@ -553,13 +604,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.categories {
|
.categories {
|
||||||
grid-template-columns: repeat(2, 300px) 175px;
|
grid-template-columns: repeat(2, 300px) 170px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1500px) {
|
@media (min-width: 1200px) {
|
||||||
.categories {
|
.categories {
|
||||||
grid-template-columns: repeat(5, 220px) 175px;
|
grid-template-columns: repeat(3, 220px) 170px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -587,25 +638,25 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
const $ = {
|
const $ = {
|
||||||
bodyClassAdd: c => $.el('body').classList.add(c),
|
bodyClassAdd: (c) => $.el('body').classList.add(c),
|
||||||
bodyClassRemove: c => $.el('body').classList.remove(c),
|
bodyClassRemove: (c) => $.el('body').classList.remove(c),
|
||||||
el: s => document.querySelector(s),
|
el: (s) => document.querySelector(s),
|
||||||
els: s => [].slice.call(document.querySelectorAll(s) || []),
|
els: (s) => [].slice.call(document.querySelectorAll(s) || []),
|
||||||
escapeRegex: s => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),
|
escapeRegex: (s) => s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),
|
||||||
flattenAndUnique: arr => [...new Set([].concat.apply([], arr))],
|
flattenAndUnique: (arr) => [...new Set([].concat.apply([], arr))],
|
||||||
ieq: (a, b) => a.toLowerCase() === b.toLowerCase(),
|
ieq: (a, b) => a.toLowerCase() === b.toLowerCase(),
|
||||||
iin: (a, b) => a.toLowerCase().indexOf(b.toLowerCase()) !== -1,
|
iin: (a, b) => a.toLowerCase().indexOf(b.toLowerCase()) !== -1,
|
||||||
isDown: e => ['ctrl-n', 'down', 'tab'].includes($.key(e)),
|
isDown: (e) => ['ctrl-n', 'down', 'tab'].includes($.key(e)),
|
||||||
isRemove: e => ['backspace', 'delete'].includes($.key(e)),
|
isRemove: (e) => ['backspace', 'delete'].includes($.key(e)),
|
||||||
isUp: e => ['ctrl-p', 'up', 's-tab'].includes($.key(e)),
|
isUp: (e) => ['ctrl-p', 'up', 's-tab'].includes($.key(e)),
|
||||||
|
|
||||||
jsonp: url => {
|
jsonp: (url) => {
|
||||||
let script = document.createElement('script');
|
let script = document.createElement('script');
|
||||||
script.src = url;
|
script.src = url;
|
||||||
$.el('head').appendChild(script);
|
$.el('head').appendChild(script);
|
||||||
},
|
},
|
||||||
|
|
||||||
key: e => {
|
key: (e) => {
|
||||||
const ctrl = e.ctrlKey;
|
const ctrl = e.ctrlKey;
|
||||||
const meta = e.metaKey;
|
const meta = e.metaKey;
|
||||||
const shift = e.shiftKey;
|
const shift = e.shiftKey;
|
||||||
@@ -649,7 +700,7 @@
|
|||||||
if (meta) return 'meta-*';
|
if (meta) return 'meta-*';
|
||||||
},
|
},
|
||||||
|
|
||||||
pad: v => ('0' + v.toString()).slice(-2),
|
pad: (v) => ('0' + v.toString()).slice(-2),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -699,8 +750,8 @@
|
|||||||
this._commands = options.commands;
|
this._commands = options.commands;
|
||||||
this._newTab = options.newTab;
|
this._newTab = options.newTab;
|
||||||
this._toggled = false;
|
this._toggled = false;
|
||||||
this._handleKeydown = this._handleKeydown.bind(this);
|
|
||||||
this.toggle = this.toggle.bind(this);
|
this.toggle = this.toggle.bind(this);
|
||||||
|
this._handleKeydown = this._handleKeydown.bind(this);
|
||||||
this._buildAndAppendLists();
|
this._buildAndAppendLists();
|
||||||
this._registerEvents();
|
this._registerEvents();
|
||||||
}
|
}
|
||||||
@@ -714,7 +765,7 @@
|
|||||||
const lists = document.createElement('ul');
|
const lists = document.createElement('ul');
|
||||||
lists.classList.add('categories');
|
lists.classList.add('categories');
|
||||||
|
|
||||||
this._getCategories().forEach(category => {
|
this._getCategories().forEach((category) => {
|
||||||
lists.insertAdjacentHTML(
|
lists.insertAdjacentHTML(
|
||||||
'beforeend',
|
'beforeend',
|
||||||
`<li class="category">
|
`<li class="category">
|
||||||
@@ -728,10 +779,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_buildListCommands(currentCategory) {
|
_buildListCommands(currentCategory) {
|
||||||
return this._commands
|
return this._commands.reduce(
|
||||||
.map(({ category, color, name, key, url }, i) => {
|
(acc, { category, color, name, key, url }, i) => {
|
||||||
if (category === currentCategory) {
|
if (category !== currentCategory) return acc;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
|
${acc}
|
||||||
<li class="command">
|
<li class="command">
|
||||||
<a href="${url}" target="${this._newTab ? '_blank' : '_self'}">
|
<a href="${url}" target="${this._newTab ? '_blank' : '_self'}">
|
||||||
${
|
${
|
||||||
@@ -744,15 +797,15 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
}
|
},
|
||||||
})
|
''
|
||||||
.join('');
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCategories() {
|
_getCategories() {
|
||||||
const categories = this._commands
|
const categories = this._commands
|
||||||
.map(v => v.category)
|
.map((v) => v.category)
|
||||||
.filter(category => category);
|
.filter((category) => category);
|
||||||
|
|
||||||
return [...new Set(categories)];
|
return [...new Set(categories)];
|
||||||
}
|
}
|
||||||
@@ -779,7 +832,7 @@
|
|||||||
|
|
||||||
_addSearchPrefix(items, query) {
|
_addSearchPrefix(items, query) {
|
||||||
const searchPrefix = this._getSearchPrefix(query);
|
const searchPrefix = this._getSearchPrefix(query);
|
||||||
return items.map(s => (searchPrefix ? searchPrefix + s : s));
|
return items.map((s) => (searchPrefix ? searchPrefix + s : s));
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSearchPrefix(query) {
|
_getSearchPrefix(query) {
|
||||||
@@ -797,10 +850,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSuggestions(query) {
|
getSuggestions(query) {
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve) =>
|
||||||
const suggestions = this._defaultSuggestions[query];
|
resolve((this._defaultSuggestions[query] || []).slice(0, this._limit))
|
||||||
resolve(suggestions ? suggestions.slice(0, this._limit) : []);
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -809,26 +861,26 @@
|
|||||||
class DuckDuckGoInfluencer extends Influencer {
|
class DuckDuckGoInfluencer extends Influencer {
|
||||||
constructor({ queryParser }) {
|
constructor({ queryParser }) {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
|
this.isAsync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSuggestions(rawQuery) {
|
getSuggestions(rawQuery) {
|
||||||
const { query } = this._parseQuery(rawQuery);
|
const { query } = this._parseQuery(rawQuery);
|
||||||
if (!query) return Promise.resolve([]);
|
if (!query) return Promise.resolve([]);
|
||||||
|
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve) => {
|
||||||
const endpoint = 'https://duckduckgo.com/ac/';
|
|
||||||
const callback = 'autocompleteCallback';
|
const callback = 'autocompleteCallback';
|
||||||
|
|
||||||
window[callback] = res => {
|
window[callback] = (res) => {
|
||||||
const suggestions = res
|
const suggestions = res
|
||||||
.map(i => i.phrase)
|
.map((i) => i.phrase)
|
||||||
.filter(s => !$.ieq(s, query))
|
.filter((s) => !$.ieq(s, query))
|
||||||
.slice(0, this._limit);
|
.slice(0, this._limit);
|
||||||
|
|
||||||
resolve(this._addSearchPrefix(suggestions, rawQuery));
|
resolve(this._addSearchPrefix(suggestions, rawQuery));
|
||||||
};
|
};
|
||||||
|
|
||||||
$.jsonp(`${endpoint}?callback=${callback}&q=${query}`);
|
$.jsonp(`https://duckduckgo.com/ac/?callback=${callback}&q=${query}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -841,6 +893,10 @@
|
|||||||
this._storeName = 'history';
|
this._storeName = 'history';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static clearHistory() {
|
||||||
|
localStorage.clear();
|
||||||
|
}
|
||||||
|
|
||||||
addItem(query) {
|
addItem(query) {
|
||||||
if (query.length < 2) return;
|
if (query.length < 2) return;
|
||||||
let exists;
|
let exists;
|
||||||
@@ -861,14 +917,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSuggestions(query) {
|
getSuggestions(query) {
|
||||||
return new Promise(resolve => {
|
return new Promise((resolve) =>
|
||||||
const suggestions = this._getHistory()
|
resolve(
|
||||||
|
this._getHistory()
|
||||||
.map(([item]) => item)
|
.map(([item]) => item)
|
||||||
.filter(item => query && !$.ieq(item, query) && $.iin(item, query))
|
.filter(
|
||||||
.slice(0, this._limit);
|
(item) => query && !$.ieq(item, query) && $.iin(item, query)
|
||||||
|
)
|
||||||
resolve(suggestions);
|
.slice(0, this._limit)
|
||||||
});
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_fetch() {
|
_fetch() {
|
||||||
@@ -894,12 +952,17 @@
|
|||||||
<script>
|
<script>
|
||||||
class Suggester {
|
class Suggester {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
this.isAsync = false;
|
||||||
this._el = $.el('#search-suggestions');
|
this._el = $.el('#search-suggestions');
|
||||||
|
this._asyncInfluencersAreBlocking = options.asyncInfluencersAreBlocking;
|
||||||
this._enabled = options.enabled;
|
this._enabled = options.enabled;
|
||||||
this._influencers = options.influencers;
|
this._influencers = options.influencers;
|
||||||
this._limit = options.limit;
|
this._limit = options.limit;
|
||||||
|
this._currentInput = '';
|
||||||
|
this._currentSuggestions = [];
|
||||||
this._suggestionEls = [];
|
this._suggestionEls = [];
|
||||||
this._handleKeydown = this._handleKeydown.bind(this);
|
this._handleKeydown = this._handleKeydown.bind(this);
|
||||||
|
this._setSuggestions = this._setSuggestions.bind(this);
|
||||||
this._registerEvents();
|
this._registerEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,36 +979,48 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
success(query) {
|
success(query) {
|
||||||
|
this._influencers.forEach((i) => i.addItem(query));
|
||||||
this._clearSuggestions();
|
this._clearSuggestions();
|
||||||
this._influencers.forEach(i => i.addItem(query));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suggest(input) {
|
suggest(input) {
|
||||||
if (!this._enabled) return;
|
if (!this._enabled) return;
|
||||||
input = input.trim();
|
this._currentInput = input.trim();
|
||||||
if (input === '') this._clearSuggestions();
|
|
||||||
|
|
||||||
Promise.all(this._getInfluencerPromises(input)).then(res => {
|
if (!this._currentInput) {
|
||||||
const suggestions = $.flattenAndUnique(res);
|
|
||||||
this._clearSuggestions();
|
this._clearSuggestions();
|
||||||
|
return;
|
||||||
if (suggestions.length) {
|
|
||||||
this._appendSuggestions(suggestions, input);
|
|
||||||
this._registerSuggestionHighlightEvents();
|
|
||||||
this._registerSuggestionClickEvents();
|
|
||||||
$.bodyClassAdd('suggestions');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_appendSuggestions(suggestions, input) {
|
this._currentSuggestions = [];
|
||||||
suggestions.some((suggestion, i) => {
|
|
||||||
const match = new RegExp($.escapeRegex(input), 'ig');
|
|
||||||
const suggestionHtml = suggestion.replace(match, `<b>${input}</b>`);
|
|
||||||
|
|
||||||
this._el.insertAdjacentHTML(
|
if (this._asyncInfluencersAreBlocking) {
|
||||||
'beforeend',
|
Promise.all(this._getInfluencers({ input })).then(this._setSuggestions);
|
||||||
`<li>
|
} else {
|
||||||
|
Promise.all(this._getInfluencers({ input, syncOnly: true })).then(
|
||||||
|
this._setSuggestions
|
||||||
|
);
|
||||||
|
|
||||||
|
Promise.all(this._getInfluencers({ input, asyncOnly: true })).then(
|
||||||
|
this._setSuggestions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildSuggestionsHtml() {
|
||||||
|
return this._currentSuggestions
|
||||||
|
.slice(0, this._limit)
|
||||||
|
.reduce((acc, suggestion) => {
|
||||||
|
const match = new RegExp($.escapeRegex(this._currentInput), 'ig');
|
||||||
|
|
||||||
|
const suggestionHtml = suggestion.replace(
|
||||||
|
match,
|
||||||
|
`<b>${this._currentInput}</b>`
|
||||||
|
);
|
||||||
|
|
||||||
|
return `
|
||||||
|
${acc}
|
||||||
|
<li>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="js-search-suggestion search-suggestion"
|
class="js-search-suggestion search-suggestion"
|
||||||
@@ -954,23 +1029,19 @@
|
|||||||
>
|
>
|
||||||
${suggestionHtml}
|
${suggestionHtml}
|
||||||
</button>
|
</button>
|
||||||
</li>`
|
</li>
|
||||||
);
|
`;
|
||||||
|
}, '');
|
||||||
if (i + 1 >= this._limit) return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._suggestionEls = $.els('.js-search-suggestion');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearSuggestionClickEvents() {
|
_clearSuggestionClickEvents() {
|
||||||
this._suggestionEls.forEach(el => {
|
this._suggestionEls.forEach((el) => {
|
||||||
el.removeEventListener('click', this._onClick);
|
el.removeEventListener('click', this._onClick);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearSuggestionHighlightEvents() {
|
_clearSuggestionHighlightEvents() {
|
||||||
this._suggestionEls.forEach(el => {
|
this._suggestionEls.forEach((el) => {
|
||||||
el.removeEventListener('mouseover', this._highlight);
|
el.removeEventListener('mouseover', this._highlight);
|
||||||
el.removeEventListener('mouseout', this._unHighlight);
|
el.removeEventListener('mouseout', this._unHighlight);
|
||||||
});
|
});
|
||||||
@@ -1006,10 +1077,15 @@
|
|||||||
if (!exists) this._unHighlight(e);
|
if (!exists) this._unHighlight(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getInfluencerPromises(input) {
|
_getInfluencers({ asyncOnly, input, syncOnly }) {
|
||||||
return this._influencers.map(influencer =>
|
return this._influencers
|
||||||
influencer.getSuggestions(input)
|
.filter(
|
||||||
);
|
(influencer) =>
|
||||||
|
(!asyncOnly && !syncOnly) ||
|
||||||
|
(asyncOnly && influencer.isAsync) ||
|
||||||
|
(syncOnly && !influencer.isAsync)
|
||||||
|
)
|
||||||
|
.map((influencer) => influencer.getSuggestions(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleKeydown(e) {
|
_handleKeydown(e) {
|
||||||
@@ -1030,7 +1106,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_registerSuggestionClickEvents() {
|
_registerSuggestionClickEvents() {
|
||||||
this._suggestionEls.forEach(el => {
|
this._suggestionEls.forEach((el) => {
|
||||||
const value = el.getAttribute('data-suggestion');
|
const value = el.getAttribute('data-suggestion');
|
||||||
el.addEventListener('click', this._onClick.bind(null, value));
|
el.addEventListener('click', this._onClick.bind(null, value));
|
||||||
});
|
});
|
||||||
@@ -1040,7 +1116,7 @@
|
|||||||
const noHighlightUntilMouseMove = () => {
|
const noHighlightUntilMouseMove = () => {
|
||||||
window.removeEventListener('mousemove', noHighlightUntilMouseMove);
|
window.removeEventListener('mousemove', noHighlightUntilMouseMove);
|
||||||
|
|
||||||
this._suggestionEls.forEach(el => {
|
this._suggestionEls.forEach((el) => {
|
||||||
el.addEventListener('mouseover', this._highlight.bind(this, el));
|
el.addEventListener('mouseover', this._highlight.bind(this, el));
|
||||||
el.addEventListener('mouseout', this._unHighlight.bind(this));
|
el.addEventListener('mouseout', this._unHighlight.bind(this));
|
||||||
});
|
});
|
||||||
@@ -1049,6 +1125,20 @@
|
|||||||
window.addEventListener('mousemove', noHighlightUntilMouseMove);
|
window.addEventListener('mousemove', noHighlightUntilMouseMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setSuggestions(newSuggestions) {
|
||||||
|
this._currentSuggestions = $.flattenAndUnique([
|
||||||
|
this._currentSuggestions,
|
||||||
|
...newSuggestions,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!this._currentSuggestions.length) return;
|
||||||
|
this._el.innerHTML = this._buildSuggestionsHtml();
|
||||||
|
this._suggestionEls = $.els('.js-search-suggestion');
|
||||||
|
this._registerSuggestionHighlightEvents();
|
||||||
|
this._registerSuggestionClickEvents();
|
||||||
|
$.bodyClassAdd('suggestions');
|
||||||
|
}
|
||||||
|
|
||||||
_unHighlight(e) {
|
_unHighlight(e) {
|
||||||
const el = $.el('.highlight');
|
const el = $.el('.highlight');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
@@ -1085,7 +1175,7 @@
|
|||||||
const splitSearch = trimmed.split(this._searchDelimiter);
|
const splitSearch = trimmed.split(this._searchDelimiter);
|
||||||
const splitPath = trimmed.split(this._pathDelimiter);
|
const splitPath = trimmed.split(this._pathDelimiter);
|
||||||
|
|
||||||
this._commands.some(({ category, key, name, search, url }) => {
|
this._commands.some(({ key, search, url }) => {
|
||||||
if (query === key) {
|
if (query === key) {
|
||||||
res.key = key;
|
res.key = key;
|
||||||
res.isKey = true;
|
res.isKey = true;
|
||||||
@@ -1127,8 +1217,8 @@
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
commands
|
commands
|
||||||
.filter(c => new URL(c.url).hostname.includes(domain))
|
.filter((c) => new URL(c.url).hostname.includes(domain))
|
||||||
.map(c => c.color)[0] || null
|
.map((c) => c.color)[0] || null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1140,7 +1230,7 @@
|
|||||||
if (!searchPath) return url;
|
if (!searchPath) return url;
|
||||||
const baseUrl = QueryParser._stripUrlPath(url);
|
const baseUrl = QueryParser._stripUrlPath(url);
|
||||||
const urlQuery = encodeURIComponent(query);
|
const urlQuery = encodeURIComponent(query);
|
||||||
searchPath = searchPath.replace('{}', urlQuery);
|
searchPath = searchPath.replace(/{}/g, urlQuery);
|
||||||
return baseUrl + searchPath;
|
return baseUrl + searchPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1287,7 +1377,7 @@
|
|||||||
searchDelimiter: CONFIG.searchDelimiter,
|
searchDelimiter: CONFIG.searchDelimiter,
|
||||||
});
|
});
|
||||||
|
|
||||||
const influencers = CONFIG.influencers.map(influencerConfig => {
|
const influencers = CONFIG.influencers.map((influencerConfig) => {
|
||||||
return new {
|
return new {
|
||||||
Default: DefaultInfluencer,
|
Default: DefaultInfluencer,
|
||||||
DuckDuckGo: DuckDuckGoInfluencer,
|
DuckDuckGo: DuckDuckGoInfluencer,
|
||||||
@@ -1300,6 +1390,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
const suggester = new Suggester({
|
const suggester = new Suggester({
|
||||||
|
asyncInfluencersAreBlocking: CONFIG.asyncInfluencersAreBlocking,
|
||||||
enabled: CONFIG.suggestions,
|
enabled: CONFIG.suggestions,
|
||||||
influencers,
|
influencers,
|
||||||
limit: CONFIG.suggestionsLimit,
|
limit: CONFIG.suggestionsLimit,
|
||||||
|
|||||||
Reference in New Issue
Block a user