Migrate to Webpack; refactor.
|
@ -25,6 +25,7 @@ module.exports = {
|
|||
semi: ["error", "never"],
|
||||
"comma-dangle": ["warn", "always-multiline"],
|
||||
quotes: ["warn", "double"],
|
||||
"no-cond-assign": ["error", "except-parens"],
|
||||
|
||||
"newline-per-chained-call": "off",
|
||||
"no-restricted-syntax": "off",
|
||||
|
|
47
README.md
|
@ -12,8 +12,8 @@ Maddy's SurfingKeys Configuration
|
|||
This is my configuration for the [SurfingKeys](https://github.com/brookhong/Surfingkeys) browser extension.
|
||||
|
||||
Its primary features include
|
||||
- 129 [Site-Specific Key Mappings](#site-specific-key-mappings) which **automate common actions** on many popular websites
|
||||
- 53 [Search Suggestion Engines](#search-suggestion-engines) providing **interactive search suggestions** from dozens of knowledge sources
|
||||
- 139 [Site-Specific Key Mappings](#site-specific-key-mappings) which **automate common actions** on many popular websites
|
||||
- 55 [Search Suggestion Engines](#search-suggestion-engines) providing **interactive search suggestions** from dozens of knowledge sources
|
||||
|
||||
Table of Contents
|
||||
-----------------
|
||||
|
@ -30,7 +30,7 @@ Features
|
|||
|
||||
### Site-Specific Key Mappings
|
||||
|
||||
129 key mappings for 21 unique
|
||||
139 key mappings for 22 unique
|
||||
sites have been included which can help you perform some common actions:
|
||||
|
||||
<table>
|
||||
|
@ -42,6 +42,7 @@ sites have been included which can help you perform some common actions:
|
|||
<tr><td><code>s</code></td><td>Scroll down</td></tr>
|
||||
<tr><td><code>K</code></td><td>Scroll half page up</td></tr>
|
||||
<tr><td><code>J</code></td><td>Scroll half page down</td></tr>
|
||||
<tr><td><code>gh</code></td><td>Scroll to element targeted by URL hash</td></tr>
|
||||
<tr><td><code>gi</code></td><td>Edit current URL with vim editor</td></tr>
|
||||
<tr><td><code>gi</code></td><td>Edit current URL with vim editor</td></tr>
|
||||
<tr><td><code>gI</code></td><td>View image in new tab</td></tr>
|
||||
|
@ -63,6 +64,7 @@ sites have been included which can help you perform some common actions:
|
|||
<tr><td><code>;pd</code></td><td>Toggle PDF viewer from SurfingKeys</td></tr>
|
||||
<tr><td><code>gxE</code></td><td>Close tab to left</td></tr>
|
||||
<tr><td><code>gxR</code></td><td>Close tab to right</td></tr>
|
||||
<tr><td><code>\cgh</code></td><td>Open clipboard string as GitHub path (e.g. 'torvalds/linux')</td></tr>
|
||||
<tr><th colspan="2"><a href="//algolia.com"><img src="./assets/favicons/algolia.com.ico" width="16px"> algolia.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>a</code></td><td>Open search result</td></tr>
|
||||
<tr><th colspan="2"><a href="//amazon.com"><img src="./assets/favicons/amazon.com.ico" width="16px"> amazon.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
|
@ -122,13 +124,23 @@ sites have been included which can help you perform some common actions:
|
|||
<tr><td><code><Space>Y</code></td><td>Copy Project Path (including domain)</td></tr>
|
||||
<tr><td><code><Space>l</code></td><td>Toggle repo language stats</td></tr>
|
||||
<tr><td><code><Space>D</code></td><td>View GoDoc for Project</td></tr>
|
||||
<tr><td><code><Space>H</code></td><td>View RepoHealth Report for Project</td></tr>
|
||||
<tr><td><code><Space>G</code></td><td>View on SourceGraph</td></tr>
|
||||
<tr><td><code><Space>ra</code></td><td>View live raw version of file</td></tr>
|
||||
<tr><td><code><Space>gcp</code></td><td>Open clipboard string as file path in repo</td></tr>
|
||||
<tr><th colspan="2"><a href="//gitlab.com"><img src="./assets/favicons/gitlab.com.ico" width="16px"> gitlab.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>s</code></td><td>Toggle Star</td></tr>
|
||||
<tr><td><code><Space>y</code></td><td>Copy Project Path</td></tr>
|
||||
<tr><td><code><Space>Y</code></td><td>Copy Project Path (including domain)</td></tr>
|
||||
<tr><td><code><Space>D</code></td><td>View GoDoc for Project</td></tr>
|
||||
<tr><th colspan="2"><a href="//home.nest.com"><img src="./assets/favicons/home.nest.com.ico" width="16px"> home.nest.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code>=</code></td><td>Increment temperature</td></tr>
|
||||
<tr><td><code>-</code></td><td>Decrement temperature</td></tr>
|
||||
<tr><td><code><Space>h</code></td><td>Switch mode to Heat</td></tr>
|
||||
<tr><td><code><Space>c</code></td><td>Switch mode to Cool</td></tr>
|
||||
<tr><td><code><Space>r</code></td><td>Switch mode to Heat/Cool</td></tr>
|
||||
<tr><td><code><Space>o</code></td><td>Switch mode to Off</td></tr>
|
||||
<tr><td><code><Space>f</code></td><td>Switch fan On</td></tr>
|
||||
<tr><td><code><Space>F</code></td><td>Switch fan Off</td></tr>
|
||||
<tr><th colspan="2"><a href="//news.ycombinator.com"><img src="./assets/favicons/news.ycombinator.com.ico" width="16px"> news.ycombinator.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>x</code></td><td>Collapse comment</td></tr>
|
||||
<tr><td><code><Space>X</code></td><td>Collapse next comment</td></tr>
|
||||
|
@ -163,19 +175,19 @@ sites have been included which can help you perform some common actions:
|
|||
<tr><td><code><Space>s</code></td><td>Like tweet</td></tr>
|
||||
<tr><td><code><Space>R</code></td><td>Retweet</td></tr>
|
||||
<tr><td><code><Space>c</code></td><td>Comment/Reply</td></tr>
|
||||
<tr><td><code><Space>t</code></td><td>New tweet</td></tr>
|
||||
<tr><td><code><Space>T</code></td><td>Tweet to</td></tr>
|
||||
<tr><td><code><Space>r</code></td><td>Load new tweets</td></tr>
|
||||
<tr><td><code><Space>g</code></td><td>Goto user</td></tr>
|
||||
<tr><td><code><Space>T</code></td><td>New tweet</td></tr>
|
||||
<tr><td><code><Space>u</code></td><td>Goto user</td></tr>
|
||||
<tr><td><code><Space>t</code></td><td>Goto tweet</td></tr>
|
||||
<tr><th colspan="2"><a href="//vimeo.com"><img src="./assets/favicons/vimeo.com.ico" width="16px"> vimeo.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>F</code></td><td>Toggle fullscreen</td></tr>
|
||||
<tr><th colspan="2"><a href="//wikipedia.org"><img src="./assets/favicons/wikipedia.org.ico" width="16px"> wikipedia.org</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>s</code></td><td>Toggle simple version of current article</td></tr>
|
||||
<tr><td><code><Space>a</code></td><td>View page</td></tr>
|
||||
<tr><td><code><Space>e</code></td><td>View external link</td></tr>
|
||||
<tr><td><code><Space>R</code></td><td>View WikiRank for current article</td></tr>
|
||||
<tr><th colspan="2"><a href="//www.google.com"><img src="./assets/favicons/www.google.com.ico" width="16px"> www.google.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>a</code></td><td>Open search result</td></tr>
|
||||
<tr><td><code><Space>A</code></td><td>Open search result (non-active new tab)</td></tr>
|
||||
<tr><td><code><Space>A</code></td><td>Open search result (new tab)</td></tr>
|
||||
<tr><td><code><Space>d</code></td><td>Open search in DuckDuckGo</td></tr>
|
||||
<tr><th colspan="2"><a href="//yelp.com"><img src="./assets/favicons/yelp.com.ico" width="16px"> yelp.com</a></th></tr><tr><td><strong>Mapping</strong></td><td><strong>Description</strong></td></tr>
|
||||
<tr><td><code><Space>fs</code></td><td>Fakespot</td></tr>
|
||||
|
@ -184,14 +196,13 @@ sites have been included which can help you perform some common actions:
|
|||
<tr><td><code>C</code></td><td>Open channel</td></tr>
|
||||
<tr><td><code>gH</code></td><td>Goto homepage</td></tr>
|
||||
<tr><td><code>F</code></td><td>Toggle fullscreen</td></tr>
|
||||
<tr><td><code><Space></code></td><td>Play/pause</td></tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
### Search Suggestion Engines
|
||||
|
||||
There are currently 53 search suggestion engines.
|
||||
There are currently 55 search suggestion engines.
|
||||
|
||||
You can access a search suggestion prompt by pressing the search leader key, which is `a` by default, followed by the search engine alias.
|
||||
|
||||
|
@ -381,6 +392,13 @@ For example, to open the Wikipedia suggestion engine, you would type `awp` while
|
|||
<td><a href="https://addons.mozilla.org">addons.mozilla.org</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://www.google.com"><img src="./assets/favicons/www.google.com.ico" width="16px"> </a></td>
|
||||
<td><code>gI</code></td>
|
||||
<td>google-reverse-image</td>
|
||||
<td><a href="https://www.google.com">www.google.com</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://godoc.org"><img src="./assets/favicons/godoc.org.ico" width="16px"> </a></td>
|
||||
<td><code>gd</code></td>
|
||||
|
@ -416,6 +434,13 @@ For example, to open the Wikipedia suggestion engine, you would type `awp` while
|
|||
<td><a href="https://www.google.com">www.google.com</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://scholar.google.com"><img src="./assets/favicons/scholar.google.com.ico" width="16px"> </a></td>
|
||||
<td><code>gs</code></td>
|
||||
<td>google-scholar</td>
|
||||
<td><a href="https://scholar.google.com">scholar.google.com</a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://gowalker.org"><img src="./assets/favicons/gowalker.org.ico" width="16px"> </a></td>
|
||||
<td><code>gw</code></td>
|
||||
|
|
129
actions.js
|
@ -26,13 +26,13 @@ actions.getURLPath = ({ count = 0, domain = false } = {}) => {
|
|||
}
|
||||
|
||||
actions.copyURLPath = ({ count, domain } = {}) => () =>
|
||||
Clipboard.write(actions.getURLPath({ count, domain }))
|
||||
Clipboard.write(actions.getURLPath({ count, domain })) // TODO: use navigator.clipboard
|
||||
|
||||
actions.copyOrgLink = () =>
|
||||
Clipboard.write(`[[${util.getCurrentLocation("href")}][${document.title}]]`)
|
||||
Clipboard.write(`[[${util.getCurrentLocation("href")}][${document.title}]]`) // TODO: use navigator.clipboard
|
||||
|
||||
actions.copyMarkdownLink = () =>
|
||||
Clipboard.write(`[${document.title}](${util.getCurrentLocation("href")})`)
|
||||
Clipboard.write(`[${document.title}](${util.getCurrentLocation("href")})`) // TODO: use navigator.clipboard
|
||||
|
||||
actions.duplicateTab = () =>
|
||||
actions.openLink(util.getCurrentLocation("href"), { newTab: true, active: false })()
|
||||
|
@ -104,7 +104,7 @@ actions.scrollToHash = (hash = null) => {
|
|||
|
||||
// Surfingkeys-specific actions
|
||||
// ----------------------------
|
||||
actions.createHint = (selector, action) => () => {
|
||||
actions.createHints = (selector, action) => () => {
|
||||
if (typeof action === "undefined") {
|
||||
// Use manual reassignment rather than a default arg so that we can lint/bundle without access
|
||||
// to the Hints object
|
||||
|
@ -137,7 +137,7 @@ actions.togglePdfViewer = () => chrome.storage.local.get("noPdfViewer", (resp) =
|
|||
}
|
||||
})
|
||||
|
||||
actions.previewLink = actions.createHint("a[href]", (a) =>
|
||||
actions.previewLink = actions.createHints("a[href]", (a) =>
|
||||
Front.showEditor(a.href, (url) => actions.openLink(url)(), "url"))
|
||||
|
||||
// FakeSpot
|
||||
|
@ -298,6 +298,7 @@ actions.dg.goog = () => {
|
|||
|
||||
// GitHub
|
||||
// ------
|
||||
// TODO: This is a mess
|
||||
actions.gh = {}
|
||||
actions.gh.star = ({ toggle = false } = {}) => async () => {
|
||||
const hasDisplayNoneParent = (e) =>
|
||||
|
@ -363,6 +364,8 @@ actions.gh.parseRepo = (url = util.getCurrentLocation(), rootOnly = false) => {
|
|||
return cond
|
||||
? {
|
||||
type: "repo",
|
||||
user,
|
||||
repo,
|
||||
owner: user,
|
||||
name: repo,
|
||||
href: url,
|
||||
|
@ -390,6 +393,7 @@ actions.gh.parseUser = (url = util.getCurrentLocation(), rootOnly = false) => {
|
|||
? {
|
||||
type: "user",
|
||||
name: user,
|
||||
user,
|
||||
href: url,
|
||||
url: u,
|
||||
userRoot: isRoot,
|
||||
|
@ -400,16 +404,17 @@ actions.gh.parseUser = (url = util.getCurrentLocation(), rootOnly = false) => {
|
|||
|
||||
actions.gh.parseFile = (url = util.getCurrentLocation()) => {
|
||||
const u = url instanceof URL ? url : new URL(url)
|
||||
const [user, repo, maybeBlob, ...rest] = u.pathname.split("/").filter((s) => s !== "")
|
||||
const [user, repo, pathType, commitHash, ...rest] = u.pathname.split("/").filter((s) => s !== "")
|
||||
const cond = (
|
||||
u.origin === util.getCurrentLocation("origin")
|
||||
&& typeof user === "string"
|
||||
&& user.length > 0
|
||||
&& typeof repo === "string"
|
||||
&& repo.length > 0
|
||||
&& typeof maybeBlob === "string"
|
||||
&& (maybeBlob === "blob" || maybeBlob === "tree")
|
||||
&& rest.length > 0
|
||||
&& typeof pathType === "string"
|
||||
&& (pathType === "blob" || pathType === "tree")
|
||||
&& typeof commitHash === "string"
|
||||
&& commitHash.length > 0
|
||||
&& /^([a-zA-Z0-9]+-?)+$/.test(user)
|
||||
&& !ghReservedNames.check(user)
|
||||
)
|
||||
|
@ -418,16 +423,19 @@ actions.gh.parseFile = (url = util.getCurrentLocation()) => {
|
|||
type: "file",
|
||||
user,
|
||||
repo,
|
||||
pathType,
|
||||
commitHash,
|
||||
href: url,
|
||||
url: u,
|
||||
filePath: rest,
|
||||
repoBase: `/${user}/${repo}`,
|
||||
}
|
||||
: null
|
||||
}
|
||||
|
||||
actions.gh.parseCommit = (url = util.getCurrentLocation()) => {
|
||||
const u = url instanceof URL ? url : new URL(url)
|
||||
const [user, repo, commit, hash] = u.pathname.split("/").filter((s) => s !== "")
|
||||
const [user, repo, commit, commitHash] = u.pathname.split("/").filter((s) => s !== "")
|
||||
const cond = (
|
||||
u.origin === util.getCurrentLocation("origin")
|
||||
&& typeof user === "string"
|
||||
|
@ -436,17 +444,19 @@ actions.gh.parseCommit = (url = util.getCurrentLocation()) => {
|
|||
&& repo.length > 0
|
||||
&& typeof commit === "string"
|
||||
&& commit === "commit"
|
||||
&& typeof hash === "string"
|
||||
&& hash.length > 0
|
||||
&& typeof commitHash === "string"
|
||||
&& commitHash.length > 0
|
||||
&& /^([a-zA-Z0-9]+-?)+$/.test(user)
|
||||
&& !ghReservedNames.check(user)
|
||||
)
|
||||
return cond
|
||||
? {
|
||||
type: "commit",
|
||||
user,
|
||||
repo,
|
||||
commitHash,
|
||||
href: url,
|
||||
url: u,
|
||||
commitHash: hash,
|
||||
}
|
||||
: null
|
||||
}
|
||||
|
@ -551,12 +561,12 @@ actions.gh.goParent = () => {
|
|||
const segments = util.getCurrentLocation("pathname")
|
||||
.split("/").filter((s) => s !== "")
|
||||
const newPath = (() => {
|
||||
const [user, repo, maybeBlob] = segments
|
||||
const [user, repo, pathType] = segments
|
||||
switch (segments.length) {
|
||||
case 0:
|
||||
return false
|
||||
case 4:
|
||||
switch (maybeBlob) {
|
||||
switch (pathType) {
|
||||
case "blob":
|
||||
case "tree":
|
||||
return [user, repo]
|
||||
|
@ -567,7 +577,7 @@ actions.gh.goParent = () => {
|
|||
}
|
||||
break
|
||||
case 5:
|
||||
if (maybeBlob === "blob") {
|
||||
if (pathType === "blob") {
|
||||
return [user, repo]
|
||||
}
|
||||
break
|
||||
|
@ -582,10 +592,33 @@ actions.gh.goParent = () => {
|
|||
}
|
||||
}
|
||||
|
||||
actions.gh.viewRepoHealth = () => {
|
||||
const repo = actions.gh.parseRepo()
|
||||
if (repo === null) return
|
||||
actions.openLink(`https://repohealth.info/report${repo.repoBase}`, { newTab: true })()
|
||||
actions.gh.viewSourceGraph = () => {
|
||||
const url = new URL("https://sourcegraph.com/github.com")
|
||||
let page = null
|
||||
// The following conditional expressions are indeed intended to be
|
||||
// assignments, this is not a bug.
|
||||
if ((page = actions.gh.parseFile(window.location.href)) !== null) {
|
||||
const filePath = page.filePath.join("/")
|
||||
url.pathname += `/${page.user}/${page.repo}@${page.commitHash}/-/${page.pathType}/${filePath}`
|
||||
if (window.location.hash !== "") {
|
||||
url.hash = window.location.hash
|
||||
} else if (!util.isElementInViewport(document.querySelector("#L1"))) {
|
||||
for (const e of document.querySelectorAll(".js-line-number")) {
|
||||
if (util.isElementInViewport(e)) {
|
||||
url.hash = e.id
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((page = actions.gh.parseCommit(window.location.href)) !== null) {
|
||||
url.pathname += `/${page.user}/${page.repo}@${page.commitHash}`
|
||||
} else if ((page = actions.gh.parseRepo(window.location.href)) !== null) {
|
||||
url.pathname += `/${page.user}/${page.repo}`
|
||||
} else {
|
||||
url.pathname = ""
|
||||
}
|
||||
|
||||
actions.openLink(url.href, { newTab: true })()
|
||||
}
|
||||
|
||||
actions.gh.viewRaw = () => {
|
||||
|
@ -594,6 +627,49 @@ actions.gh.viewRaw = () => {
|
|||
actions.openLink(`https://raw.githack.com/${file.user}/${file.repo}/${file.filePath.join("/")}`, { newTab: true })()
|
||||
}
|
||||
|
||||
actions.gh.openRepoFromClipboard = async ({ newTab = true } = {}) =>
|
||||
actions.openLink(`https://github.com/${await navigator.clipboard.readText()}`, { newTab })()
|
||||
|
||||
actions.gh.openFileFromClipboard = async ({ newTab = true } = {}) => {
|
||||
const clip = await navigator.clipboard.readText()
|
||||
if (typeof clip !== "string" || clip.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const loc = util.getCurrentLocation()
|
||||
const dest = {
|
||||
user: null,
|
||||
repo: null,
|
||||
commitHash: "master",
|
||||
}
|
||||
|
||||
const file = actions.gh.parseFile(loc)
|
||||
if (file !== null) {
|
||||
dest.user = file.user
|
||||
dest.repo = file.repo
|
||||
dest.commitHash = file.commitHash
|
||||
} else {
|
||||
const commit = actions.gh.parseCommit(loc)
|
||||
if (commit !== null) {
|
||||
dest.user = commit.user
|
||||
dest.repo = commit.repo
|
||||
dest.commitHash = commit.commitHash
|
||||
} else {
|
||||
const repository = actions.gh.parseRepo(loc)
|
||||
if (repository !== null) {
|
||||
return
|
||||
}
|
||||
dest.user = repository.user
|
||||
dest.repo = repository.repo
|
||||
}
|
||||
}
|
||||
|
||||
actions.openLink(
|
||||
`https://github.com/${dest.user}/${dest.repo}/tree/${dest.commitHash}/${clip}`,
|
||||
{ newTab },
|
||||
)()
|
||||
}
|
||||
|
||||
// GitLab
|
||||
// ------
|
||||
actions.gl = {}
|
||||
|
@ -609,6 +685,17 @@ actions.gl.star = () => {
|
|||
Front.showBanner(`${star} Repository ${repo} ${action}`)
|
||||
}
|
||||
|
||||
// Twitter
|
||||
// ------
|
||||
actions.tw = {}
|
||||
actions.tw.openUser = () =>
|
||||
actions.createHints([].concat(
|
||||
[...document.querySelectorAll("a[role='link'] img[src^='https://pbs.twimg.com/profile_images']")]
|
||||
.map((e) => e.closest("a")),
|
||||
[...document.querySelectorAll("a[role='link']")]
|
||||
.filter((e) => e.text.match(/^@/)),
|
||||
))()
|
||||
|
||||
// Reddit
|
||||
// ------
|
||||
actions.re = {}
|
||||
|
@ -696,7 +783,7 @@ actions.ph.openExternal = () => {
|
|||
// Dribbble
|
||||
// --------
|
||||
actions.dr = {}
|
||||
actions.dr.attachment = (cb = (a) => actions.openLink(a, { newTab: true })()) => actions.createHint(".attachments .thumb", (a) => cb(a.src.replace("/thumbnail/", "/")))
|
||||
actions.dr.attachment = (cb = (a) => actions.openLink(a, { newTab: true })()) => actions.createHints(".attachments .thumb", (a) => cb(a.src.replace("/thumbnail/", "/")))
|
||||
|
||||
// Wikipedia
|
||||
// ---------
|
||||
|
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -1 +1 @@
|
|||
{"www.archlinux.org":"www.archlinux.org.ico","aur.archlinux.org":"aur.archlinux.org.ico","wiki.archlinux.org":"wiki.archlinux.org.ico","bbs.archlinux.org":"bbs.archlinux.org.ico","alternativeto.net":"alternativeto.net.ico","chrome.google.com":"chrome.google.com.ico","addons.mozilla.org":"addons.mozilla.org.ico","www.owasp.org":"www.owasp.org.ico","stackoverflow.com":"stackoverflow.com.ico","stackexchange.com":"stackexchange.com.ico","hub.docker.com":"hub.docker.com.ico","github.com":"github.com.ico","domainr.com":"domainr.com.ico","vim.fandom.com":"vim.fandom.com.ico","smile.amazon.com":"smile.amazon.com.ico","www.craigslist.org":"www.craigslist.org.ico","www.ebay.com":"www.ebay.com.ico","www.yelp.com":"www.yelp.com.ico","onelook.com":"onelook.com.ico","www.onelook.com":"www.onelook.com.ico","en.wikipedia.org":"en.wikipedia.org.ico","simple.wikipedia.org":"simple.wikipedia.org.ico","en.wiktionary.org":"en.wiktionary.org.ico","www.wolframalpha.com":"www.wolframalpha.com.ico","www.crunchbase.com":"www.crunchbase.com.ico","duckduckgo.com":"duckduckgo.com.ico","www.google.com":"www.google.com.ico","hex.pm":"hex.pm.ico","golang.org":"golang.org.ico","godoc.org":"godoc.org.ico","gowalker.org":"gowalker.org.ico","hackage.haskell.org":"hackage.haskell.org.ico","www.haskell.org":"www.haskell.org.ico","wiki.haskell.org":"wiki.haskell.org.ico","jquery.com":"jquery.com.ico","nodejs.org":"nodejs.org.ico","developer.mozilla.org":"developer.mozilla.org.ico","www.npmjs.com":"www.npmjs.com.ico","news.ycombinator.com":"news.ycombinator.com.ico","www.reddit.com":"www.reddit.com.ico","www.youtube.com":"www.youtube.com.ico","amazon.com":"amazon.com.ico","algolia.com":"algolia.com.ico","yelp.com":"yelp.com.ico","youtube.com":"youtube.com.ico","vimeo.com":"vimeo.com.ico","gitlab.com":"gitlab.com.ico","twitter.com":"twitter.com.ico","reddit.com":"reddit.com.ico","producthunt.com":"producthunt.com.ico","dribbble.com":"dribbble.com.ico","behance.net":"behance.net.ico","fonts.adobe.com":"fonts.adobe.com.ico","wikipedia.org":"wikipedia.org.ico","craigslist.org":"craigslist.org.ico"}
|
||||
{"www.archlinux.org":"www.archlinux.org.ico","aur.archlinux.org":"aur.archlinux.org.ico","wiki.archlinux.org":"wiki.archlinux.org.ico","bbs.archlinux.org":"bbs.archlinux.org.ico","alternativeto.net":"alternativeto.net.ico","chrome.google.com":"chrome.google.com.ico","addons.mozilla.org":"addons.mozilla.org.ico","www.owasp.org":"www.owasp.org.ico","stackoverflow.com":"stackoverflow.com.ico","stackexchange.com":"stackexchange.com.ico","hub.docker.com":"hub.docker.com.ico","github.com":"github.com.ico","domainr.com":"domainr.com.ico","vim.fandom.com":"vim.fandom.com.ico","smile.amazon.com":"smile.amazon.com.ico","www.craigslist.org":"www.craigslist.org.ico","www.ebay.com":"www.ebay.com.ico","www.yelp.com":"www.yelp.com.ico","onelook.com":"onelook.com.ico","www.onelook.com":"www.onelook.com.ico","en.wikipedia.org":"en.wikipedia.org.ico","simple.wikipedia.org":"simple.wikipedia.org.ico","en.wiktionary.org":"en.wiktionary.org.ico","www.wolframalpha.com":"www.wolframalpha.com.ico","www.crunchbase.com":"www.crunchbase.com.ico","duckduckgo.com":"duckduckgo.com.ico","www.google.com":"www.google.com.ico","scholar.google.com":"scholar.google.com.ico","hex.pm":"hex.pm.ico","golang.org":"golang.org.ico","godoc.org":"godoc.org.ico","gowalker.org":"gowalker.org.ico","hackage.haskell.org":"hackage.haskell.org.ico","www.haskell.org":"www.haskell.org.ico","wiki.haskell.org":"wiki.haskell.org.ico","jquery.com":"jquery.com.ico","nodejs.org":"nodejs.org.ico","developer.mozilla.org":"developer.mozilla.org.ico","www.npmjs.com":"www.npmjs.com.ico","news.ycombinator.com":"news.ycombinator.com.ico","www.reddit.com":"www.reddit.com.ico","www.youtube.com":"www.youtube.com.ico","amazon.com":"amazon.com.ico","algolia.com":"algolia.com.ico","yelp.com":"yelp.com.ico","youtube.com":"youtube.com.ico","vimeo.com":"vimeo.com.ico","gitlab.com":"gitlab.com.ico","twitter.com":"twitter.com.ico","reddit.com":"reddit.com.ico","producthunt.com":"producthunt.com.ico","dribbble.com":"dribbble.com.ico","behance.net":"behance.net.ico","fonts.adobe.com":"fonts.adobe.com.ico","wikipedia.org":"wikipedia.org.ico","craigslist.org":"craigslist.org.ico","home.nest.com":"home.nest.com.ico"}
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 498 B |
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 8.5 KiB |
|
@ -5,6 +5,8 @@ const wpDefaultIcon = "data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20enco
|
|||
|
||||
const cbDefaultIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAAAAAByaaZbAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAACYktHRAD/h4/MvwAAAAlwSFlzAAAOwwAADsMBx2+oZAAAAAd0SU1FB+EICxEMErRVWUQAAABOdEVYdFJhdyBwcm9maWxlIHR5cGUgZXhpZgAKZXhpZgogICAgICAyMAo0NTc4Njk2NjAwMDA0OTQ5MmEwMDA4MDAwMDAwMDAwMDAwMDAwMDAwCnwMkD0AAAGXSURBVEjH1ZRvc4IwDMb7/T8dbVr/sEPlPJQd3g22GzJdmxVOHaQa8N2WN7wwvyZ5Eh/hngzxTwDr0If/TAK67POxbqxnpgCIx9dkrkEvswYnAFiutFSgtQapS4ejwFYqbXQXBmC+QxawuI/MJb0LiCq0DICNHoZRKQdYLKQZEhATcQmwDYD5GR8DDtfqaYAMActvTiVMaUvqhZPVYhYAK2SBAwGMTHngnc4wVmFPW9L6k1PJxbSCkfvhqolKSQhsWSClizNyxwAWdzIADixQRXRmdWSHthsg+TknaztFMZgC3vh/nG/qo68TLAKrCSrUg1ulp3cH+BpItBp3DZf0lFXVOIDnBdwKkLO4D5Q3QMO6HJ+hUb1NKNWMGJn3jf4ejPKn99CXOtsuyab95obGL/rpdZ7oIJK87iPiumG01drbdggoCZuq/f0XaB8/FbG62Ta5cD97XJwuZUT7ONbZTIK5m94hBuQs8535MsL5xxPw6ZoNj0DiyzhhcyMf9BJ0Jk1uRRpNyb4y0UaM9UI7E8+kt/EHgR/R6042JzmiwgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wOC0xMVQxNzoxMjoxOC0wNDowMLy29LgAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDgtMTFUMTc6MTI6MTgtMDQ6MDDN60wEAAAAAElFTkSuQmCC"
|
||||
|
||||
const locale = typeof navigator !== "undefined" ? navigator.language : ""
|
||||
|
||||
const completions = {}
|
||||
|
||||
// Helper functions for Google Custom Search Engine completions
|
||||
|
@ -167,7 +169,7 @@ const parseFirefoxAddonsRes = (response) => JSON.parse(response.text).results.ma
|
|||
completions.fa = {
|
||||
alias: "fa",
|
||||
name: "firefox-addons",
|
||||
search: "https://addons.mozilla.org/en-US/firefox/search/?q=",
|
||||
search: `https://addons.mozilla.org/${locale}/firefox/search/?q=`,
|
||||
compl: "https://addons.mozilla.org/api/v4/addons/autocomplete/?q=",
|
||||
callback: parseFirefoxAddonsRes,
|
||||
}
|
||||
|
@ -176,7 +178,7 @@ completions.fa = {
|
|||
completions.ft = {
|
||||
alias: "ft",
|
||||
name: "firefox-themes",
|
||||
search: "https://addons.mozilla.org/en-US/firefox/search/?type=statictheme&q=",
|
||||
search: `https://addons.mozilla.org/${locale}/firefox/search/?type=statictheme&q=`,
|
||||
compl: "https://addons.mozilla.org/api/v4/addons/autocomplete/?type=statictheme&q=",
|
||||
callback: parseFirefoxAddonsRes,
|
||||
}
|
||||
|
@ -185,7 +187,7 @@ completions.ft = {
|
|||
completions.fe = {
|
||||
alias: "fe",
|
||||
name: "firefox-extensions",
|
||||
search: "https://addons.mozilla.org/en-US/firefox/search/?type=extension&q=",
|
||||
search: `https://addons.mozilla.org/${locale}/firefox/search/?type=extension&q=`,
|
||||
compl: "https://addons.mozilla.org/api/v4/addons/autocomplete/?type=extension&q=",
|
||||
callback: parseFirefoxAddonsRes,
|
||||
}
|
||||
|
@ -983,8 +985,8 @@ completions.no = {
|
|||
completions.md = {
|
||||
alias: "md",
|
||||
name: "mdn",
|
||||
search: "https://developer.mozilla.org/en-US/search?q=",
|
||||
compl: "https://developer.mozilla.org/en-US/search.json?q=",
|
||||
search: `https://developer.mozilla.org/${locale}/search?q=`,
|
||||
compl: `https://developer.mozilla.org/api/v1/search/${locale}?q=`,
|
||||
}
|
||||
|
||||
completions.md.callback = (response) => {
|
||||
|
@ -1005,7 +1007,7 @@ completions.md.callback = (response) => {
|
|||
<div style="font-size:0.8em"><em>${slug}</em></div>
|
||||
<div>${excerpt}</div>
|
||||
</div>
|
||||
`, { url: `https://developer.mozilla.org/${s.slug}` })
|
||||
`, { url: `https://developer.mozilla.org/${s.locale}/docs/${s.slug}` })
|
||||
})
|
||||
}
|
||||
|
||||
|
|
4
conf.js
|
@ -8,6 +8,10 @@ util.addSettings({
|
|||
omnibarSuggestionTimeout: 500,
|
||||
richHintsForKeystroke: 1,
|
||||
theme: `
|
||||
body {
|
||||
font-family: "DejaVu Sans", DejaVu, Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Disable RichHints CSS animation */
|
||||
.expandRichHints {
|
||||
animation: 0s ease-in-out 1 forwards expandRichHints;
|
||||
|
|
84
gulpfile.js
|
@ -3,7 +3,9 @@ const gulp = require("gulp")
|
|||
const { task, src, dest } = gulp
|
||||
const { parallel, series } = gulp
|
||||
|
||||
const parcel = require("gulp-parcel")
|
||||
const webpack = require("webpack")
|
||||
const webpackStream = require("webpack-stream")
|
||||
|
||||
const replace = require("gulp-replace")
|
||||
const rename = require("gulp-rename")
|
||||
const eslint = require("gulp-eslint")
|
||||
|
@ -15,11 +17,14 @@ const fs = require("fs").promises
|
|||
const fetch = require("node-fetch")
|
||||
const express = require("express")
|
||||
const gulpIf = require("gulp-if")
|
||||
const gulpNotify = require("gulp-notify")
|
||||
const PluginError = require("plugin-error")
|
||||
|
||||
const { COPYFILE_EXCL } = require("fs").constants
|
||||
const { URL } = require("url")
|
||||
|
||||
const pkg = require("./package.json")
|
||||
const webpackConfig = require("./webpack.config.js")
|
||||
|
||||
const copyrightYearOne = 2017
|
||||
|
||||
|
@ -34,6 +39,7 @@ const paths = {
|
|||
faviconsManifest: "favicons.json",
|
||||
readmeOut: "README.md",
|
||||
scriptOut: "surfingkeys.js",
|
||||
buildDir: "build/",
|
||||
installDir: platforms.getConfigHome(),
|
||||
}
|
||||
|
||||
|
@ -82,13 +88,48 @@ The source file is ${paths.readme}
|
|||
|
||||
-->`
|
||||
|
||||
task("clean", () => del(["build", ".cache", ".tmp-gulp-compile-*"]))
|
||||
const notify = Object.assign((opts, ...args) => gulpNotify({
|
||||
icon: null,
|
||||
onLast: true,
|
||||
timeout: 2000,
|
||||
...opts,
|
||||
}, ...args), gulpNotify)
|
||||
|
||||
notify.onError = (opts, ...args) => gulpNotify.onError({
|
||||
onLast: true,
|
||||
timeout: 7500,
|
||||
...opts,
|
||||
}, ...args)
|
||||
|
||||
task("clean", () => del(["build", ".cache", ".tmp-gulp-compile-*"]))
|
||||
task("clean-favicons", () => del([paths.favicons]))
|
||||
|
||||
const lint = (globs, opts = {}) => gulp.src(globs)
|
||||
.pipe(eslint(opts))
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.results((res) => {
|
||||
if (res.warningCount + res.errorCount > 0) {
|
||||
const msg = []
|
||||
if (res.warningCount > 0) {
|
||||
msg.push(`${res.warningCount} warning${res.warningCount === 1 ? "" : "s"}`)
|
||||
}
|
||||
if (res.errorCount > 0) {
|
||||
msg.push(`${res.errorCount} error${res.errorCount === 1 ? "" : "s"}`)
|
||||
}
|
||||
const numBadFiles = res.reduce((acc, e) =>
|
||||
(e.errorCount + e.warningCount > 0 ? acc + 1 : acc),
|
||||
0)
|
||||
const err = new PluginError("gulp-eslint", {
|
||||
name: "ESLintError",
|
||||
message: `${msg.join(" and ")} in ${numBadFiles} file${numBadFiles === 1 ? "" : "s"}`,
|
||||
})
|
||||
notify.onError({
|
||||
title: `Lint failure [${pkg.name}]`,
|
||||
message: err.message,
|
||||
})(err)
|
||||
throw err
|
||||
}
|
||||
}))
|
||||
|
||||
task("lint", () => lint([...paths.scripts, paths.gulpfile]))
|
||||
|
||||
|
@ -295,24 +336,41 @@ task("favicons", series("clean-favicons", async () => {
|
|||
|
||||
task("docs-full", series("favicons", "docs"))
|
||||
|
||||
const build = () =>
|
||||
src(paths.entry)
|
||||
.pipe(webpackStream(webpackConfig, webpack))
|
||||
.on("error", (err) => {
|
||||
notify.onError({
|
||||
title: `Build failure [${pkg.name}]`,
|
||||
message: `${err.message.split("\n").slice(0, 1)}`,
|
||||
})(err)
|
||||
throw err
|
||||
})
|
||||
.pipe(rename(paths.scriptOut))
|
||||
.pipe(dest(paths.buildDir))
|
||||
.pipe(notify({
|
||||
title: `Build success [${pkg.name}]`,
|
||||
message: "No issues",
|
||||
}))
|
||||
|
||||
task("build",
|
||||
parallel(
|
||||
"lint",
|
||||
build,
|
||||
))
|
||||
|
||||
task("build-full",
|
||||
series(
|
||||
parallel(
|
||||
"check-priv",
|
||||
"clean",
|
||||
),
|
||||
parallel(
|
||||
"lint",
|
||||
() => src(paths.entry, { read: false })
|
||||
.pipe(parcel())
|
||||
.pipe(rename(paths.scriptOut))
|
||||
.pipe(dest("build")),
|
||||
),
|
||||
"build",
|
||||
))
|
||||
|
||||
task("dist", parallel("docs-full", "build"))
|
||||
task("dist", parallel("docs-full", "build-full"))
|
||||
|
||||
task("install", series("build", () => src(path.join("build", paths.scriptOut))
|
||||
task("install", series("build", () => src(path.join(paths.buildDir, paths.scriptOut))
|
||||
.pipe(dest(paths.installDir))))
|
||||
|
||||
const watch = (g, t) => () =>
|
||||
|
@ -334,7 +392,7 @@ const serve = (done) => {
|
|||
const handler = (allowedOrigin) => async (req, res) => {
|
||||
console.log(`${new Date().toISOString()} ${req.method} ${req.url}`) // eslint-disable-line no-console
|
||||
try {
|
||||
res.sendFile(path.resolve(__dirname, "build", paths.scriptOut), {
|
||||
res.sendFile(path.resolve(__dirname, paths.buildDir, paths.scriptOut), {
|
||||
headers: {
|
||||
"Content-Type": "text/javascript; charset=UTF-8",
|
||||
"Access-Control-Allow-Origin": allowedOrigin,
|
||||
|
@ -366,3 +424,5 @@ task("serve-build", parallel("watch-build", "serve-simple"))
|
|||
task("serve", series("serve-build"))
|
||||
task("watch", series("watch-install"))
|
||||
task("default", series("build"))
|
||||
|
||||
// debugger
|
||||
|
|
256
keys.js
|
@ -20,8 +20,9 @@ const unmaps = {
|
|||
},
|
||||
}
|
||||
|
||||
const maps = {
|
||||
global: [
|
||||
const maps = {}
|
||||
|
||||
maps.global = [
|
||||
{
|
||||
alias: "F",
|
||||
map: "gf",
|
||||
|
@ -58,6 +59,12 @@ const maps = {
|
|||
category: categories.scroll,
|
||||
description: "Scroll half page down",
|
||||
},
|
||||
{
|
||||
alias: "gh",
|
||||
category: categories.scroll,
|
||||
description: "Scroll to element targeted by URL hash",
|
||||
callback: actions.scrollToHash,
|
||||
},
|
||||
{
|
||||
alias: "gi",
|
||||
category: categories.pageNav,
|
||||
|
@ -74,7 +81,7 @@ const maps = {
|
|||
alias: "gI",
|
||||
category: categories.pageNav,
|
||||
description: "View image in new tab",
|
||||
callback: actions.createHint("img", (i) => actions.openLink(i.src)()),
|
||||
callback: actions.createHints("img", (i) => actions.openLink(i.src)()),
|
||||
},
|
||||
{
|
||||
alias: "yp",
|
||||
|
@ -86,7 +93,8 @@ const maps = {
|
|||
alias: "yI",
|
||||
category: categories.clipboard,
|
||||
description: "Copy Image URL",
|
||||
callback: actions.createHint("img", (i) => Clipboard.write(i.src)),
|
||||
// TODO: use navigator.clipboard
|
||||
callback: actions.createHints("img", (i) => Clipboard.write(i.src)),
|
||||
},
|
||||
{
|
||||
alias: "yO",
|
||||
|
@ -184,14 +192,14 @@ const maps = {
|
|||
description: "Close tab to right",
|
||||
},
|
||||
{
|
||||
alias: "gh",
|
||||
alias: "\\cgh",
|
||||
category: categories.clipboard,
|
||||
description: "Scroll to element targeted by URL hash",
|
||||
callback: actions.scrollToHash,
|
||||
description: "Open clipboard string as GitHub path (e.g. 'torvalds/linux')",
|
||||
callback: actions.gh.openRepoFromClipboard,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"amazon.com": [
|
||||
maps["amazon.com"] = [
|
||||
{
|
||||
alias: "fs",
|
||||
description: "Fakespot",
|
||||
|
@ -205,7 +213,7 @@ const maps = {
|
|||
{
|
||||
alias: "c",
|
||||
description: "Add to Cart",
|
||||
callback: actions.createHint("#add-to-cart-button"),
|
||||
callback: actions.createHints("#add-to-cart-button"),
|
||||
},
|
||||
{
|
||||
alias: "R",
|
||||
|
@ -232,44 +240,58 @@ const maps = {
|
|||
description: "Open Orders page",
|
||||
callback: actions.openLink("/gp/css/order-history"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"www.google.com": [
|
||||
const googleSearchResultSelector = [
|
||||
"a h3",
|
||||
"h3 a",
|
||||
"a[href^='/search']:not(.fl):not(#pnnext,#pnprev):not([role]):not(.hide-focus-ring)",
|
||||
"g-scrolling-carousel a",
|
||||
".rc > div:nth-child(2) a",
|
||||
".kno-rdesc a",
|
||||
".kno-fv a",
|
||||
".isv-r > a:first-child",
|
||||
".dbsr > a:first-child",
|
||||
].join(",")
|
||||
|
||||
maps["www.google.com"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "Open search result",
|
||||
callback: actions.createHint("a.fl, .r>a"),
|
||||
callback: actions.createHints(googleSearchResultSelector),
|
||||
},
|
||||
{
|
||||
alias: "A",
|
||||
description: "Open search result (non-active new tab)",
|
||||
callback: actions.createHint("a.fl, .r>a", actions.openAnchor({ newTab: true, active: false })),
|
||||
description: "Open search result (new tab)",
|
||||
callback: actions.createHints(googleSearchResultSelector,
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
{
|
||||
alias: "d",
|
||||
description: "Open search in DuckDuckGo",
|
||||
callback: actions.go.ddg,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"algolia.com": [
|
||||
maps["algolia.com"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "Open search result",
|
||||
callback: actions.createHint(".item-main h2>a:first-child"),
|
||||
callback: actions.createHints(".item-main h2>a:first-child"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"duckduckgo.com": [
|
||||
maps["duckduckgo.com"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "Open search result",
|
||||
callback: actions.createHint(".result__a"),
|
||||
callback: actions.createHints(".result__a"),
|
||||
},
|
||||
{
|
||||
alias: "A",
|
||||
description: "Open search result (non-active new tab)",
|
||||
callback: actions.createHint(".result__a", actions.openAnchor({ newTab: true, active: false })),
|
||||
callback: actions.createHints(".result__a",
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
{
|
||||
leader: "",
|
||||
|
@ -282,28 +304,29 @@ const maps = {
|
|||
description: "Open search in Google",
|
||||
callback: actions.dg.goog,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"yelp.com": [
|
||||
maps["yelp.com"] = [
|
||||
{
|
||||
alias: "fs",
|
||||
description: "Fakespot",
|
||||
callback: actions.fakeSpot,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"youtube.com": [
|
||||
maps["youtube.com"] = [
|
||||
{
|
||||
leader: "",
|
||||
alias: "A",
|
||||
description: "Open video",
|
||||
callback: actions.createHint("*[id='video-title']", actions.openAnchor({ newTab: true })),
|
||||
callback: actions.createHints("*[id='video-title']",
|
||||
actions.openAnchor({ newTab: true })),
|
||||
},
|
||||
{
|
||||
leader: "",
|
||||
alias: "C",
|
||||
description: "Open channel",
|
||||
callback: actions.createHint("*[id='byline']"),
|
||||
callback: actions.createHints("*[id='byline']"),
|
||||
},
|
||||
{
|
||||
leader: "",
|
||||
|
@ -317,17 +340,17 @@ const maps = {
|
|||
description: "Toggle fullscreen",
|
||||
callback: () => document.querySelector(".ytp-fullscreen-button.ytp-button").click(),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"vimeo.com": [
|
||||
maps["vimeo.com"] = [
|
||||
{
|
||||
alias: "F",
|
||||
description: "Toggle fullscreen",
|
||||
callback: () => document.querySelector(".fullscreen-icon").click(),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"github.com": [
|
||||
maps["github.com"] = [
|
||||
{
|
||||
alias: "A",
|
||||
description: "Open repository Actions page",
|
||||
|
@ -411,7 +434,7 @@ const maps = {
|
|||
{
|
||||
alias: "e",
|
||||
description: "View external link",
|
||||
callback: actions.createHint("a[rel=nofollow]"),
|
||||
callback: actions.createHints("a[rel=nofollow]"),
|
||||
},
|
||||
{ // TODO: Add repetition support: 3gu
|
||||
leader: "",
|
||||
|
@ -445,18 +468,23 @@ const maps = {
|
|||
callback: actions.viewGodoc,
|
||||
},
|
||||
{
|
||||
alias: "H",
|
||||
description: "View RepoHealth Report for Project",
|
||||
callback: actions.gh.viewRepoHealth,
|
||||
alias: "G",
|
||||
description: "View on SourceGraph",
|
||||
callback: actions.gh.viewSourceGraph,
|
||||
},
|
||||
{
|
||||
alias: "ra",
|
||||
description: "View live raw version of file",
|
||||
callback: actions.gh.viewRaw,
|
||||
},
|
||||
],
|
||||
{
|
||||
alias: "gcp",
|
||||
description: "Open clipboard string as file path in repo",
|
||||
callback: actions.gh.openFileFromClipboard,
|
||||
},
|
||||
]
|
||||
|
||||
"gitlab.com": [
|
||||
maps["gitlab.com"] = [
|
||||
{
|
||||
alias: "s",
|
||||
description: "Toggle Star",
|
||||
|
@ -477,56 +505,51 @@ const maps = {
|
|||
description: "View GoDoc for Project",
|
||||
callback: actions.viewGodoc,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"twitter.com": [
|
||||
maps["twitter.com"] = [
|
||||
{
|
||||
alias: "f",
|
||||
description: "Follow user",
|
||||
callback: actions.createHint(".follow-button"),
|
||||
callback: actions.createHints("div[role='button'][data-testid$='follow']"),
|
||||
},
|
||||
{
|
||||
alias: "s",
|
||||
description: "Like tweet",
|
||||
callback: actions.createHint(".js-actionFavorite"),
|
||||
callback: actions.createHints("div[role='button'][data-testid$='like']"),
|
||||
},
|
||||
{
|
||||
alias: "R",
|
||||
description: "Retweet",
|
||||
callback: actions.createHint(".js-actionRetweet"),
|
||||
callback: actions.createHints("div[role='button'][data-testid$='retweet']"),
|
||||
},
|
||||
{
|
||||
alias: "c",
|
||||
description: "Comment/Reply",
|
||||
callback: actions.createHint(".js-actionReply"),
|
||||
},
|
||||
{
|
||||
alias: "t",
|
||||
description: "New tweet",
|
||||
callback: actions.createHint(".js-global-new-tweet"),
|
||||
callback: actions.createHints("div[role='button'][data-testid='reply']"),
|
||||
},
|
||||
{
|
||||
alias: "T",
|
||||
description: "Tweet to",
|
||||
callback: actions.createHint(".NewTweetButton"),
|
||||
description: "New tweet",
|
||||
callback: () => document.querySelector("a[role='button'][data-testid='SideNav_NewTweet_Button']").click(),
|
||||
},
|
||||
{
|
||||
alias: "r",
|
||||
description: "Load new tweets",
|
||||
callback: actions.createHint(".new-tweets-bar"),
|
||||
},
|
||||
{
|
||||
alias: "g",
|
||||
alias: "u",
|
||||
description: "Goto user",
|
||||
callback: actions.createHint(".js-user-profile-link"),
|
||||
callback: actions.tw.openUser,
|
||||
},
|
||||
],
|
||||
{
|
||||
alias: "t",
|
||||
description: "Goto tweet",
|
||||
callback: actions.createHints("article, article div[data-focusable='true'][role='link'][tabindex='0']"),
|
||||
},
|
||||
]
|
||||
|
||||
"reddit.com": [
|
||||
maps["reddit.com"] = [
|
||||
{
|
||||
alias: "x",
|
||||
description: "Collapse comment",
|
||||
callback: actions.createHint(".expand"),
|
||||
callback: actions.createHints(".expand"),
|
||||
},
|
||||
{
|
||||
alias: "X",
|
||||
|
@ -536,45 +559,47 @@ const maps = {
|
|||
{
|
||||
alias: "s",
|
||||
description: "Upvote",
|
||||
callback: actions.createHint(".arrow.up"),
|
||||
callback: actions.createHints(".arrow.up"),
|
||||
},
|
||||
{
|
||||
alias: "S",
|
||||
description: "Downvote",
|
||||
callback: actions.createHint(".arrow.down"),
|
||||
callback: actions.createHints(".arrow.down"),
|
||||
},
|
||||
{
|
||||
alias: "e",
|
||||
description: "Expand expando",
|
||||
callback: actions.createHint(".expando-button"),
|
||||
callback: actions.createHints(".expando-button"),
|
||||
},
|
||||
{
|
||||
alias: "a",
|
||||
description: "View post (link)",
|
||||
callback: actions.createHint(".title"),
|
||||
callback: actions.createHints(".title"),
|
||||
},
|
||||
{
|
||||
alias: "A",
|
||||
description: "View post (link) (non-active new tab)",
|
||||
callback: actions.createHint(".title", actions.openAnchor({ newTab: true, active: false })),
|
||||
callback: actions.createHints(".title",
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
{
|
||||
alias: "c",
|
||||
description: "View post (comments)",
|
||||
callback: actions.createHint(".comments"),
|
||||
callback: actions.createHints(".comments"),
|
||||
},
|
||||
{
|
||||
alias: "C",
|
||||
description: "View post (comments) (non-active new tab)",
|
||||
callback: actions.createHint(".comments", actions.openAnchor({ newTab: true, active: false })),
|
||||
callback: actions.createHints(".comments",
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"news.ycombinator.com": [
|
||||
maps["news.ycombinator.com"] = [
|
||||
{
|
||||
alias: "x",
|
||||
description: "Collapse comment",
|
||||
callback: actions.createHint(".togg"),
|
||||
callback: actions.createHints(".togg"),
|
||||
},
|
||||
{
|
||||
alias: "X",
|
||||
|
@ -584,37 +609,38 @@ const maps = {
|
|||
{
|
||||
alias: "s",
|
||||
description: "Upvote",
|
||||
callback: actions.createHint(".votearrow[title='upvote']"),
|
||||
callback: actions.createHints(".votearrow[title='upvote']"),
|
||||
},
|
||||
{
|
||||
alias: "S",
|
||||
description: "Downvote",
|
||||
callback: actions.createHint(".votearrow[title='downvote']"),
|
||||
callback: actions.createHints(".votearrow[title='downvote']"),
|
||||
},
|
||||
{
|
||||
alias: "a",
|
||||
description: "View post (link)",
|
||||
callback: actions.createHint(".storylink"),
|
||||
callback: actions.createHints(".storylink"),
|
||||
},
|
||||
{
|
||||
alias: "A",
|
||||
description: "View post (link and comments)",
|
||||
callback: actions.createHint(".athing", actions.hn.openLinkAndComments),
|
||||
callback: actions.createHints(".athing", actions.hn.openLinkAndComments),
|
||||
},
|
||||
{
|
||||
alias: "c",
|
||||
description: "View post (comments)",
|
||||
callback: actions.createHint("td > a[href*='item']:not(.storylink)"),
|
||||
callback: actions.createHints("td > a[href*='item']:not(.storylink)"),
|
||||
},
|
||||
{
|
||||
alias: "C",
|
||||
description: "View post (comments) (non-active new tab)",
|
||||
callback: actions.createHint("td > a[href*='item']:not(.storylink)", actions.openAnchor({ newTab: true, active: false })),
|
||||
callback: actions.createHints("td > a[href*='item']:not(.storylink)",
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
{
|
||||
alias: "e",
|
||||
description: "View external link",
|
||||
callback: actions.createHint("a[rel=nofollow]"),
|
||||
callback: actions.createHints("a[rel=nofollow]"),
|
||||
},
|
||||
{
|
||||
leader: "",
|
||||
|
@ -634,9 +660,9 @@ const maps = {
|
|||
description: "Prev page",
|
||||
callback: () => actions.hn.goPage(-1),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"producthunt.com": [
|
||||
maps["producthunt.com"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "View product (external)",
|
||||
|
@ -645,30 +671,31 @@ const maps = {
|
|||
{
|
||||
alias: "v",
|
||||
description: "View product",
|
||||
callback: actions.createHint("ul[class^='postsList_'] > li > div[class^='item_'] > a"),
|
||||
callback: actions.createHints("ul[class^='postsList_'] > li > div[class^='item_'] > a"),
|
||||
},
|
||||
{
|
||||
alias: "s",
|
||||
description: "Upvote product",
|
||||
callback: actions.createHint("button[data-test='vote-button']"),
|
||||
callback: actions.createHints("button[data-test='vote-button']"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"dribbble.com": [
|
||||
maps["dribbble.com"] = [
|
||||
{
|
||||
alias: "s",
|
||||
description: "Heart Shot",
|
||||
callback: actions.createHint(".toggle-fav, .like-shot"),
|
||||
callback: actions.createHints(".toggle-fav, .like-shot"),
|
||||
},
|
||||
{
|
||||
alias: "a",
|
||||
description: "View shot",
|
||||
callback: actions.createHint(".dribbble-over, .gif-target, .more-thumbs a"),
|
||||
callback: actions.createHints(".dribbble-over, .gif-target, .more-thumbs a"),
|
||||
},
|
||||
{
|
||||
alias: "A",
|
||||
description: "View shot (non-active new tab)",
|
||||
callback: actions.createHint(".dribbble-over, .gif-target, .more-thumbs a", actions.openAnchor({ newTab: true, active: false })),
|
||||
callback: actions.createHints(".dribbble-over, .gif-target, .more-thumbs a",
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
{
|
||||
alias: "v",
|
||||
|
@ -678,20 +705,21 @@ const maps = {
|
|||
{
|
||||
alias: "V",
|
||||
description: "Yank attachment image source URL",
|
||||
// TODO: use navigator.clipboard
|
||||
callback: actions.dr.attachment((a) => Clipboard.write(a)),
|
||||
},
|
||||
{
|
||||
alias: "z",
|
||||
description: "Zoom shot",
|
||||
callback: actions.createHint(".single-img picture, .detail-shot img"),
|
||||
callback: actions.createHints(".single-img picture, .detail-shot img"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"behance.net": [
|
||||
maps["behance.net"] = [
|
||||
{
|
||||
alias: "s",
|
||||
description: "Appreciate project",
|
||||
callback: actions.createHint(".appreciation-button"),
|
||||
callback: actions.createHints(".appreciation-button"),
|
||||
},
|
||||
{
|
||||
alias: "b",
|
||||
|
@ -701,29 +729,30 @@ const maps = {
|
|||
{
|
||||
alias: "a",
|
||||
description: "View project",
|
||||
callback: actions.createHint(".rf-project-cover__title"),
|
||||
callback: actions.createHints(".rf-project-cover__title"),
|
||||
},
|
||||
{
|
||||
alias: "A",
|
||||
description: "View project (non-active new tab)",
|
||||
callback: actions.createHint(".rf-project-cover__title", actions.openAnchor({ newTab: true, active: false })),
|
||||
callback: actions.createHints(".rf-project-cover__title",
|
||||
actions.openAnchor({ newTab: true, active: false })),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"fonts.adobe.com": [
|
||||
maps["fonts.adobe.com"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "Activate font",
|
||||
callback: actions.createHint(".spectrum-ToggleSwitch-input"),
|
||||
callback: actions.createHints(".spectrum-ToggleSwitch-input"),
|
||||
},
|
||||
{
|
||||
alias: "s",
|
||||
description: "Favorite font",
|
||||
callback: actions.createHint(".favorite-toggle-icon"),
|
||||
callback: actions.createHints(".favorite-toggle-icon"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"wikipedia.org": [
|
||||
maps["wikipedia.org"] = [
|
||||
{
|
||||
alias: "s",
|
||||
description: "Toggle simple version of current article",
|
||||
|
@ -732,45 +761,45 @@ const maps = {
|
|||
{
|
||||
alias: "a",
|
||||
description: "View page",
|
||||
callback: actions.createHint("#bodyContent :not(sup):not(.mw-editsection) > a:not([rel=nofollow])"),
|
||||
callback: actions.createHints("#bodyContent :not(sup):not(.mw-editsection) > a:not([rel=nofollow])"),
|
||||
},
|
||||
{
|
||||
alias: "e",
|
||||
description: "View external link",
|
||||
callback: actions.createHint("a[rel=nofollow]"),
|
||||
callback: actions.createHints("a[rel=nofollow]"),
|
||||
},
|
||||
{
|
||||
alias: "R",
|
||||
description: "View WikiRank for current article",
|
||||
callback: actions.wp.viewWikiRank,
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"craigslist.org": [
|
||||
maps["craigslist.org"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "View listing",
|
||||
callback: actions.createHint("a.result-title"),
|
||||
callback: actions.createHints("a.result-title"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"stackoverflow.com": [
|
||||
maps["stackoverflow.com"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "View question",
|
||||
callback: actions.createHint("a.question-hyperlink"),
|
||||
callback: actions.createHints("a.question-hyperlink"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"aur.archlinux.org": [
|
||||
maps["aur.archlinux.org"] = [
|
||||
{
|
||||
alias: "a",
|
||||
description: "View package",
|
||||
callback: actions.createHint("a[href^='/packages/'][href$='/']"),
|
||||
callback: actions.createHints("a[href^='/packages/'][href$='/']"),
|
||||
},
|
||||
],
|
||||
]
|
||||
|
||||
"home.nest.com": [
|
||||
maps["home.nest.com"] = [
|
||||
{
|
||||
path: "/thermostat/DEVICE_.*",
|
||||
leader: "",
|
||||
|
@ -821,8 +850,7 @@ const maps = {
|
|||
description: "Switch fan Off",
|
||||
callback: actions.nt.setFan(0),
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
// Aliases
|
||||
const aliases = {
|
||||
|
|
27
package.json
|
@ -20,30 +20,25 @@
|
|||
"contributors": [],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"github-reserved-names": "^1.1.9"
|
||||
"github-reserved-names": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"del": "^5.1.0",
|
||||
"eslint": "7.3.1",
|
||||
"eslint-config-airbnb-base": "14.2.0",
|
||||
"eslint-plugin-import": "^2.22.0",
|
||||
"del": "^6.0.0",
|
||||
"eslint": "7.16.0",
|
||||
"eslint-config-airbnb-base": "14.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"express": "^4.17.1",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-eslint": "^6.0.0",
|
||||
"gulp-file": "^0.4.0",
|
||||
"gulp-if": "^3.0.0",
|
||||
"gulp-parcel": "^0.3.6",
|
||||
"gulp-notify": "^3.2.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-replace": "^1.0.0",
|
||||
"json5": "^2.1.1",
|
||||
"node-fetch": "^2.6.0",
|
||||
"platform-folders": "^0.5.1"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
"node-fetch": "^2.6.1",
|
||||
"platform-folders": "^0.5.2",
|
||||
"plugin-error": "^1.0.1",
|
||||
"webpack": "^5.11.1",
|
||||
"webpack-stream": "^6.1.1"
|
||||
}
|
||||
}
|
||||
|
|
2
util.js
|
@ -149,7 +149,7 @@ util.processCompletions = (completions, searchleader) => Object.values(completio
|
|||
addSearchAliasX(s.alias, s.name, s.search, searchleader, s.compl, s.callback)
|
||||
mapkey(`${searchleader}${s.alias}`, `#8Search ${s.name}`, () => Front.openOmnibar({ type: "SearchEngine", extra: s.alias }))
|
||||
mapkey(`c${searchleader}${s.alias}`, `#8Search ${s.name} with clipboard contents`, () => {
|
||||
Clipboard.read((c) => {
|
||||
Clipboard.read((c) => { // TODO: use navigator.clipboard
|
||||
Front.openOmnibar({ type: "SearchEngine", pref: c.data, extra: s.alias })
|
||||
})
|
||||
})
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
mode: "development",
|
||||
}
|