refactor: add lots of stuff
sorry I changed too much and don't wanna go back and split it all into separate commits.....
This commit is contained in:
parent
0f20918354
commit
f1535b2668
|
@ -0,0 +1,187 @@
|
||||||
|
const util = require("./util")
|
||||||
|
|
||||||
|
const actions = {}
|
||||||
|
|
||||||
|
// Globally applicable actions
|
||||||
|
// ===========================
|
||||||
|
|
||||||
|
// URL Manipulation/querying
|
||||||
|
// -------------------------
|
||||||
|
actions.vimEditURL = () => Front
|
||||||
|
.showEditor(window.location.href, (data) => {
|
||||||
|
window.location.href = data
|
||||||
|
}, "url")
|
||||||
|
|
||||||
|
actions.getURLPath = ({ count = 0, domain = false } = {}) => {
|
||||||
|
let path = window.location.pathname.slice(1)
|
||||||
|
if (count) {
|
||||||
|
path = path.split("/").slice(0, count).join("/")
|
||||||
|
}
|
||||||
|
if (domain) {
|
||||||
|
path = `${window.location.hostname}/${path}`
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.copyURLPath = ({ count, domain } = {}) =>
|
||||||
|
() => Clipboard.write(actions.getURLPath({ count, domain }))
|
||||||
|
|
||||||
|
// Whois/DNS lookup
|
||||||
|
// ----------------
|
||||||
|
const domainDossierUrl = "http://centralops.net/co/DomainDossier.aspx"
|
||||||
|
|
||||||
|
actions.showWhois = ({ hostname = window.location.hostname } = {}) =>
|
||||||
|
() => tabOpenLink(`${domainDossierUrl}?dom_whois=true&addr=${hostname}`)
|
||||||
|
|
||||||
|
actions.showDns = ({ hostname = window.location.hostname, verbose = false } = {}) =>
|
||||||
|
() => {
|
||||||
|
if (verbose) {
|
||||||
|
tabOpenLink(`${domainDossierUrl}?dom_whois=true&dom_dns=true&traceroute=true&net_whois=true&svc_scan=true&addr=${hostname}`)
|
||||||
|
} else {
|
||||||
|
tabOpenLink(`${domainDossierUrl}?dom_dns=true&addr=${hostname}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surfingkeys-specific actions
|
||||||
|
// ----------------------------
|
||||||
|
actions.createHint = (selector, action = Hints.dispatchMouseClick) =>
|
||||||
|
() => Hints.create(selector, action)
|
||||||
|
|
||||||
|
actions.open = ({ newTab = false, prop = "href" } = {}) => a => window.open(a[prop], newTab ? "_BLANK" : undefined)
|
||||||
|
|
||||||
|
actions.editSettings = () => tabOpenLink("/pages/options.html")
|
||||||
|
|
||||||
|
actions.togglePdfViewer = () =>
|
||||||
|
chrome.storage.local.get("noPdfViewer", (resp) => {
|
||||||
|
if (!resp.noPdfViewer) {
|
||||||
|
chrome.storage.local.set({ noPdfViewer: 1 }, () => {
|
||||||
|
Front.showBanner("PDF viewer disabled.")
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
chrome.storage.local.remove("noPdfViewer", () => {
|
||||||
|
Front.showBanner("PDF viewer enabled.")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Site-specific actions
|
||||||
|
// =====================
|
||||||
|
|
||||||
|
// FakeSpot
|
||||||
|
// --------
|
||||||
|
actions.fakeSpot = (url = window.location.href) => tabOpenLink(`http://fakespot.com/analyze?url=${url}`)
|
||||||
|
|
||||||
|
// Godoc
|
||||||
|
// -----
|
||||||
|
actions.viewGodoc = () =>
|
||||||
|
tabOpenLink(`https://godoc.org/${actions.getURLPath({ count: 2, domain: true })}`)
|
||||||
|
|
||||||
|
// GitHub
|
||||||
|
// ------
|
||||||
|
actions.gh = {}
|
||||||
|
actions.gh.star = ({ toggle = false } = {}) => () => {
|
||||||
|
const repo = window.location.pathname.slice(1).split("/").slice(0, 2).join("/")
|
||||||
|
const container = document.querySelector("div.starring-container")
|
||||||
|
const status = container.classList.contains("on")
|
||||||
|
|
||||||
|
let star = "★"
|
||||||
|
let statusMsg = "starred"
|
||||||
|
let verb = "is"
|
||||||
|
|
||||||
|
if ((status && toggle) || (!status && !toggle)) {
|
||||||
|
statusMsg = `un${statusMsg}`
|
||||||
|
star = "☆"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toggle) {
|
||||||
|
verb = "has been"
|
||||||
|
if (status) {
|
||||||
|
container.querySelector(".starred>button").click()
|
||||||
|
} else {
|
||||||
|
container.querySelector(".unstarred>button").click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Front.showBanner(`${star} Repository ${repo} ${verb} ${statusMsg}!`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitLab
|
||||||
|
// ------
|
||||||
|
actions.gl = {}
|
||||||
|
actions.gl.star = () => {
|
||||||
|
const repo = window.location.pathname.slice(1).split("/").slice(0, 2).join("/")
|
||||||
|
const btn = document.querySelector(".btn.star-btn > span")
|
||||||
|
btn.click()
|
||||||
|
const action = `${btn.textContent.toLowerCase()}red`
|
||||||
|
let star = "☆"
|
||||||
|
if (action === "starred") {
|
||||||
|
star = "★"
|
||||||
|
}
|
||||||
|
Front.showBanner(`${star} Repository ${repo} ${action}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reddit
|
||||||
|
// ------
|
||||||
|
actions.re = {}
|
||||||
|
actions.re.collapseNextComment = () => {
|
||||||
|
const vis = Array.from(document.querySelectorAll(".noncollapsed.comment"))
|
||||||
|
.filter(e => util.isElementInViewport(e))
|
||||||
|
if (vis.length > 0) {
|
||||||
|
vis[0].querySelector(".expand").click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unfortunately, this does not work - Reddit will only load the first
|
||||||
|
// Expando
|
||||||
|
actions.re.toggleVisibleExpandos = (dir = 0) => () => {
|
||||||
|
let sel = ".expando-button"
|
||||||
|
if (dir === -1) {
|
||||||
|
sel += ".expanded"
|
||||||
|
} else if (dir === 1) {
|
||||||
|
sel += ".collapsed"
|
||||||
|
}
|
||||||
|
console.log(sel)
|
||||||
|
Array.from(document.querySelectorAll(sel))
|
||||||
|
.filter(e => util.isElementInViewport(e))
|
||||||
|
.forEach(e => e.click())
|
||||||
|
}
|
||||||
|
|
||||||
|
// HackerNews
|
||||||
|
// ----------
|
||||||
|
actions.hn = {}
|
||||||
|
actions.hn.goParent = () => {
|
||||||
|
const par = document.querySelector(".par>a")
|
||||||
|
if (!par) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
window.location.assign(par.href)
|
||||||
|
}
|
||||||
|
|
||||||
|
actions.hn.collapseNextComment = () => {
|
||||||
|
const vis = Array.from(document.querySelectorAll("a.togg"))
|
||||||
|
.filter(e => e.innerText === "[-]" && util.isElementInViewport(e))
|
||||||
|
if (vis.length > 0) {
|
||||||
|
vis[0].click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dribbble
|
||||||
|
// --------
|
||||||
|
actions.dr = {}
|
||||||
|
actions.dr.attachment = (cb = a => tabOpenLink(a)) =>
|
||||||
|
actions.createHint(".attachments .thumb", a => cb(a.src.replace("/thumbnail/", "/")))
|
||||||
|
|
||||||
|
// Wikipedia
|
||||||
|
// ---------
|
||||||
|
actions.wp = {}
|
||||||
|
actions.wp.toggleSimple = () => {
|
||||||
|
window.location.hostname = window.location.hostname.split(".")
|
||||||
|
.map((s, i) => {
|
||||||
|
if (i === 0) {
|
||||||
|
return s === "simple" ? "" : "simple"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}).filter(s => s !== "").join(".")
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = actions
|
|
@ -1,39 +1,20 @@
|
||||||
const { keys } = require("./conf.priv.js")
|
const { keys } = require("./conf.priv.js")
|
||||||
|
const { escape, createSuggestionItem, createURLItem } = require("./util")
|
||||||
|
|
||||||
function escape(str) {
|
const completions = {}
|
||||||
return String(str).replace(/[&<>"'`=/]/g, s => ({
|
|
||||||
"&": "&",
|
// Helper functions for Google Custom Search Engine completions
|
||||||
"<": "<",
|
const googleCxURL = (alias) => {
|
||||||
">": ">",
|
const key = `google_cx_${alias}`
|
||||||
"\"": """,
|
return `https://www.googleapis.com/customsearch/v1?key=${keys.google_cs}&cx=${keys[key]}&q=`
|
||||||
"'": "'",
|
|
||||||
"/": "/",
|
|
||||||
"`": "`",
|
|
||||||
"=": "=",
|
|
||||||
}[s]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSuggestionItem(html, props = {}) {
|
const googleCxPublicURL = (alias) => {
|
||||||
const li = document.createElement("li")
|
const key = `google_cx_${alias}`
|
||||||
li.innerHTML = html
|
return `https://cse.google.com/cse/publicurl?cx=${keys[key]}&q=`
|
||||||
return { html: li.outerHTML, props }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createURLItem(title, url, sanitize = true) {
|
const googleCxCallback = (response) => {
|
||||||
let t = title
|
|
||||||
let u = url
|
|
||||||
if (sanitize) {
|
|
||||||
t = escape(t)
|
|
||||||
u = new URL(u).toString()
|
|
||||||
}
|
|
||||||
return createSuggestionItem(`
|
|
||||||
<div class="title">${t}</div>
|
|
||||||
<div class="url">${u}</div>
|
|
||||||
`, { url: u })
|
|
||||||
}
|
|
||||||
|
|
||||||
// ****** Helper Functions ****** //
|
|
||||||
function googleCxCallback(response) {
|
|
||||||
const res = JSON.parse(response.text).items
|
const res = JSON.parse(response.text).items
|
||||||
return res.map(s => createSuggestionItem(`
|
return res.map(s => createSuggestionItem(`
|
||||||
<div>
|
<div>
|
||||||
|
@ -43,19 +24,6 @@ function googleCxCallback(response) {
|
||||||
`, { url: s.link }))
|
`, { url: s.link }))
|
||||||
}
|
}
|
||||||
|
|
||||||
function googleCxURL(alias) {
|
|
||||||
const key = `google_cx_${alias}`
|
|
||||||
return `https://www.googleapis.com/customsearch/v1?key=${keys.google_cs}&cx=${keys[key]}&q=`
|
|
||||||
}
|
|
||||||
|
|
||||||
function googleCxPublicURL(alias) {
|
|
||||||
const key = `google_cx_${alias}`
|
|
||||||
return `https://cse.google.com/cse/publicurl?cx=${keys[key]}&q=`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ****** Completions ****** //
|
|
||||||
const completions = {}
|
|
||||||
|
|
||||||
// ****** Arch Linux ****** //
|
// ****** Arch Linux ****** //
|
||||||
|
|
||||||
// Arch Linux official repos
|
// Arch Linux official repos
|
||||||
|
@ -330,13 +298,14 @@ const wpNoimg = "data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3
|
||||||
completions.wp.callback = response => Object.values(JSON.parse(response.text).query.pages)
|
completions.wp.callback = response => Object.values(JSON.parse(response.text).query.pages)
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
const img = p.thumbnail ? p.thumbnail.source : wpNoimg
|
const img = p.thumbnail ? p.thumbnail.source : wpNoimg
|
||||||
|
const desc = p.description ? p.description : ""
|
||||||
return createSuggestionItem(
|
return createSuggestionItem(
|
||||||
`
|
`
|
||||||
<div style="padding:5px;display:grid;grid-template-columns:60px 1fr;grid-gap:15px">
|
<div style="padding:5px;display:grid;grid-template-columns:60px 1fr;grid-gap:15px">
|
||||||
<img style="width:60px" src="${img}" alt="${p.title}">
|
<img style="width:60px" src="${img}" alt="${p.title}">
|
||||||
<div>
|
<div>
|
||||||
<div class="title"><strong>${p.title}</strong></div>
|
<div class="title"><strong>${p.title}</strong></div>
|
||||||
<div class="title">${p.description}</div>
|
<div class="title">${desc}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
|
348
conf.js
348
conf.js
|
@ -1,33 +1,6 @@
|
||||||
|
const util = require("./util")
|
||||||
|
const keys = require("./keys")
|
||||||
const completions = require("./completions")
|
const completions = require("./completions")
|
||||||
const { isElementInViewport } = require("./util")
|
|
||||||
|
|
||||||
// Unmap undesired defaults
|
|
||||||
const unmaps = [
|
|
||||||
"sb", "sw", "ob",
|
|
||||||
"ow", "cp", ";cp",
|
|
||||||
";ap", "spa", "spb",
|
|
||||||
"spd", "sps", "spc",
|
|
||||||
"spi", "sfr", "zQ",
|
|
||||||
"zz", "zR", "ab",
|
|
||||||
"Q", "q", "ag",
|
|
||||||
"af", ";s", "yp",
|
|
||||||
]
|
|
||||||
|
|
||||||
unmaps.forEach((u) => {
|
|
||||||
unmap(u)
|
|
||||||
})
|
|
||||||
|
|
||||||
const rmSearchAliases =
|
|
||||||
{
|
|
||||||
s: ["g", "d", "b",
|
|
||||||
"w", "s", "h"],
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(rmSearchAliases).forEach((k) => {
|
|
||||||
rmSearchAliases[k].forEach((v) => {
|
|
||||||
removeSearchAliasX(v, k)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// ---- Settings ----//
|
// ---- Settings ----//
|
||||||
settings.hintAlign = "left"
|
settings.hintAlign = "left"
|
||||||
|
@ -45,314 +18,15 @@ settings.theme = `
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
// ---- Maps ----//
|
// Leader for site-specific mappings
|
||||||
// Left-hand aliases
|
|
||||||
// Movement
|
|
||||||
map("w", "k")
|
|
||||||
map("s", "j")
|
|
||||||
|
|
||||||
// Right-hand aliases
|
|
||||||
// Tab Navigation
|
|
||||||
map("J", "E")
|
|
||||||
map("K", "R")
|
|
||||||
|
|
||||||
// History
|
|
||||||
map("H", "S")
|
|
||||||
map("L", "D")
|
|
||||||
|
|
||||||
|
|
||||||
// ---- Functions ----//
|
|
||||||
|
|
||||||
const vimEditURL = () => Front
|
|
||||||
.showEditor(window.location.href, (data) => {
|
|
||||||
window.location.href = data
|
|
||||||
}, "url")
|
|
||||||
|
|
||||||
const domainDossier = "http://centralops.net/co/DomainDossier.aspx"
|
|
||||||
|
|
||||||
const whois = () =>
|
|
||||||
tabOpenLink(`${domainDossier}?dom_whois=true&addr=${window.location.hostname}`)
|
|
||||||
|
|
||||||
const dns = () =>
|
|
||||||
tabOpenLink(`${domainDossier}?dom_dns=true&addr=${window.location.hostname}`)
|
|
||||||
|
|
||||||
const dnsVerbose = () =>
|
|
||||||
tabOpenLink(`${domainDossier}?dom_whois=true&dom_dns=true&traceroute=true&net_whois=true&svc_scan=true&addr=${window.location.hostname}`)
|
|
||||||
|
|
||||||
const togglePdfViewer = () =>
|
|
||||||
chrome.storage.local.get("noPdfViewer", (resp) => {
|
|
||||||
if (!resp.noPdfViewer) {
|
|
||||||
chrome.storage.local.set({ noPdfViewer: 1 }, () => {
|
|
||||||
Front.showBanner("PDF viewer disabled.")
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
chrome.storage.local.remove("noPdfViewer", () => {
|
|
||||||
Front.showBanner("PDF viewer enabled.")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const getURLPath = (count, domain) => {
|
|
||||||
let path = window.location.pathname.slice(1)
|
|
||||||
if (count) {
|
|
||||||
path = path.split("/").slice(0, count).join("/")
|
|
||||||
}
|
|
||||||
if (domain) {
|
|
||||||
path = `${window.location.hostname}/${path}`
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
const copyURLPath = (count, domain) => () => Clipboard.write(getURLPath(count, domain))
|
|
||||||
|
|
||||||
const editSettings = () => tabOpenLink("/pages/options.html")
|
|
||||||
|
|
||||||
const Hint = (selector, action = Hints.dispatchMouseClick) => () => Hints.create(selector, action)
|
|
||||||
|
|
||||||
// ---- Mapkeys ----//
|
|
||||||
const ri = { repeatIgnore: true }
|
|
||||||
|
|
||||||
// --- Global mappings ---//
|
|
||||||
// 0: Help
|
|
||||||
// 1: Mouse Click
|
|
||||||
// 2: Scroll Page / Element
|
|
||||||
// 3: Tabs
|
|
||||||
// 4: Page Navigation
|
|
||||||
mapkey("gi", "#4Edit current URL with vim editor", vimEditURL, ri)
|
|
||||||
mapkey("gI", "#4View image in new tab", Hint("img", i => tabOpenLink(i.src)), ri)
|
|
||||||
// 5: Sessions
|
|
||||||
// 6: Search selected with
|
|
||||||
// 7: Clipboard
|
|
||||||
mapkey("yp", "#7Copy URL path of current page", copyURLPath(), ri)
|
|
||||||
mapkey("yI", "#7Copy Image URL", Hint("img", i => Clipboard.write(i.src)), ri)
|
|
||||||
// 8: Omnibar
|
|
||||||
// 9: Visual Mode
|
|
||||||
// 10: vim-like marks
|
|
||||||
// 11: Settings
|
|
||||||
mapkey(";se", "#11Edit Settings", editSettings, ri)
|
|
||||||
// 12: Chrome URLs
|
|
||||||
mapkey("gS", "#12Open Chrome settings", () => tabOpenLink("chrome://settings/"))
|
|
||||||
// 13: Proxy
|
|
||||||
// 14: Misc
|
|
||||||
mapkey("=w", "#14Lookup whois information for domain", whois, ri)
|
|
||||||
mapkey("=d", "#14Lookup dns information for domain", dns, ri)
|
|
||||||
mapkey("=D", "#14Lookup all information for domain", dnsVerbose, ri)
|
|
||||||
mapkey(";pd", "#14Toggle PDF viewer from SurfingKeys", togglePdfViewer, ri)
|
|
||||||
// 15: Insert Mode
|
|
||||||
|
|
||||||
// --- Site-specific mappings ---//
|
|
||||||
const siteleader = "<Space>"
|
const siteleader = "<Space>"
|
||||||
|
|
||||||
function mapsitekey(domainRegex, key, desc, f, opts = {}) {
|
// Leader for OmniBar searchEngines
|
||||||
const o = Object.assign({}, {
|
const searchleader = "a"
|
||||||
leader: siteleader,
|
|
||||||
}, opts)
|
|
||||||
mapkey(`${o.leader}${key}`, desc, f, { domain: domainRegex })
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapsitekeys(d, maps, opts = {}) {
|
// Process mappings and completions
|
||||||
const domain = d.replace(".", "\\.")
|
// See ./keys.js and ./completions.js
|
||||||
const domainRegex = new RegExp(`^http(s)?://(([a-zA-Z0-9-_]+\\.)*)(${domain})(/.*)?`)
|
util.rmMaps(keys.unmaps.mappings)
|
||||||
maps.forEach((map) => {
|
util.rmSearchAliases(keys.unmaps.searchAliases)
|
||||||
const [
|
util.processMaps(keys.maps, siteleader)
|
||||||
key,
|
util.processCompletions(completions, searchleader)
|
||||||
desc,
|
|
||||||
f,
|
|
||||||
subOpts = {},
|
|
||||||
] = map
|
|
||||||
mapsitekey(domainRegex, key, desc, f, Object.assign({}, opts, subOpts))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const fakeSpot = () => tabOpenLink(`http://fakespot.com/analyze?url=${window.location.href}`)
|
|
||||||
|
|
||||||
mapsitekeys("amazon.com", [
|
|
||||||
["fs", "Fakespot", fakeSpot],
|
|
||||||
])
|
|
||||||
|
|
||||||
mapsitekeys("yelp.com", [
|
|
||||||
["fs", "Fakespot", fakeSpot],
|
|
||||||
])
|
|
||||||
|
|
||||||
const ytFullscreen = () => document
|
|
||||||
.querySelector(".ytp-fullscreen-button.ytp-button")
|
|
||||||
.click()
|
|
||||||
|
|
||||||
mapsitekeys("youtube.com", [
|
|
||||||
["A", "Open video", Hint("*[id='video-title']")],
|
|
||||||
["C", "Open channel", Hint("*[id='byline']")],
|
|
||||||
["gH", "Goto homepage", () => window.location.assign("https://www.youtube.com/feed/subscriptions?flow=2")],
|
|
||||||
["F", "Toggle fullscreen", ytFullscreen],
|
|
||||||
["<Space>", "Play/pause", Hint(".ytp-play-button")],
|
|
||||||
], { leader: "" })
|
|
||||||
|
|
||||||
|
|
||||||
const vimeoFullscreen = () => document
|
|
||||||
.querySelector(".fullscreen-icon")
|
|
||||||
.click()
|
|
||||||
|
|
||||||
mapsitekeys("vimeo.com", [
|
|
||||||
["F", "Toggle fullscreen", vimeoFullscreen],
|
|
||||||
])
|
|
||||||
|
|
||||||
const ghStar = toggle => () => {
|
|
||||||
const repo = window.location.pathname.slice(1).split("/").slice(0, 2).join("/")
|
|
||||||
const container = document.querySelector("div.starring-container")
|
|
||||||
const status = container.classList.contains("on")
|
|
||||||
|
|
||||||
let star = "★"
|
|
||||||
let statusMsg = "starred"
|
|
||||||
let verb = "is"
|
|
||||||
|
|
||||||
if ((status && toggle) || (!status && !toggle)) {
|
|
||||||
statusMsg = `un${statusMsg}`
|
|
||||||
star = "☆"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toggle) {
|
|
||||||
verb = "has been"
|
|
||||||
if (status) {
|
|
||||||
container.querySelector(".starred>button").click()
|
|
||||||
} else {
|
|
||||||
container.querySelector(".unstarred>button").click()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Front.showBanner(`${star} Repository ${repo} ${verb} ${statusMsg}!`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const viewGodoc = () => tabOpenLink(`https://godoc.org/${getURLPath(2, true)}`)
|
|
||||||
|
|
||||||
mapsitekeys("github.com", [
|
|
||||||
["s", "Toggle Star", ghStar(true)],
|
|
||||||
["S", "Check Star", ghStar(false)],
|
|
||||||
["y", "Copy Project Path", copyURLPath(2)],
|
|
||||||
["Y", "Copy Project Path (including domain)", copyURLPath(2, true)],
|
|
||||||
["D", "View GoDoc for Project", viewGodoc],
|
|
||||||
])
|
|
||||||
|
|
||||||
const glToggleStar = () => {
|
|
||||||
const repo = window.location.pathname.slice(1).split("/").slice(0, 2).join("/")
|
|
||||||
const btn = document.querySelector(".btn.star-btn > span")
|
|
||||||
btn.click()
|
|
||||||
const action = `${btn.textContent.toLowerCase()}red`
|
|
||||||
let star = "☆"
|
|
||||||
if (action === "starred") {
|
|
||||||
star = "★"
|
|
||||||
}
|
|
||||||
Front.showBanner(`${star} Repository ${repo} ${action}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
mapsitekeys("gitlab.com", [
|
|
||||||
["s", "Toggle Star", glToggleStar],
|
|
||||||
["y", "Copy Project Path", copyURLPath(2)],
|
|
||||||
["Y", "Copy Project Path (including domain)", copyURLPath(2, true)],
|
|
||||||
["D", "View GoDoc for Project", viewGodoc],
|
|
||||||
])
|
|
||||||
|
|
||||||
mapsitekeys("twitter.com", [
|
|
||||||
["f", "Follow user", Hint(".follow-button")],
|
|
||||||
["s", "Like tweet", Hint(".js-actionFavorite")],
|
|
||||||
["R", "Retweet", Hint(".js-actionRetweet")],
|
|
||||||
["c", "Comment/Reply", Hint(".js-actionReply")],
|
|
||||||
["t", "New tweet", Hint(".js-global-new-tweet")],
|
|
||||||
["T", "Tweet to", Hint(".NewTweetButton")],
|
|
||||||
["r", "Load new tweets", Hint(".new-tweets-bar")],
|
|
||||||
["g", "Goto user", Hint(".js-user-profile-link")],
|
|
||||||
])
|
|
||||||
|
|
||||||
const redditCollapseNextComment = () => {
|
|
||||||
const vis = Array.from(document.querySelectorAll(".noncollapsed.comment"))
|
|
||||||
.filter(e => isElementInViewport(e))
|
|
||||||
if (vis.length > 0) {
|
|
||||||
vis[0].querySelector(".expand").click()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mapsitekeys("reddit.com", [
|
|
||||||
["x", "Collapse comment", Hint(".expand")],
|
|
||||||
["X", "Collapse next comment", redditCollapseNextComment],
|
|
||||||
["s", "Upvote", Hint(".arrow.up")],
|
|
||||||
["S", "Downvote", Hint(".arrow.down")],
|
|
||||||
["e", "Expand expando", Hint(".expando-button")],
|
|
||||||
["a", "View post (link)", Hint(".title")],
|
|
||||||
["c", "View post (comments)", Hint(".comments")],
|
|
||||||
])
|
|
||||||
|
|
||||||
const hnGoParent = () => {
|
|
||||||
const par = document.querySelector(".par>a")
|
|
||||||
if (!par) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
window.location.assign(par.href)
|
|
||||||
}
|
|
||||||
|
|
||||||
const hnCollapseNextComment = () => {
|
|
||||||
const vis = Array.from(document.querySelectorAll("a.togg"))
|
|
||||||
.filter(e => e.innerText === "[-]" && isElementInViewport(e))
|
|
||||||
if (vis.length > 0) {
|
|
||||||
vis[0].click()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mapsitekeys("news.ycombinator.com", [
|
|
||||||
["x", "Collapse comment", Hint(".togg")],
|
|
||||||
["X", "Collapse next comment", hnCollapseNextComment],
|
|
||||||
["s", "Upvote", Hint(".votearrow[title='upvote']")],
|
|
||||||
["S", "Downvote", Hint(".votearrow[title='downvote']")],
|
|
||||||
["a", "View post (link)", Hint(".storylink")],
|
|
||||||
["c", "View post (comments)", Hint("td > a[href*='item']:not(.storylink)")],
|
|
||||||
["p", "Go to parent", hnGoParent],
|
|
||||||
])
|
|
||||||
|
|
||||||
const dribbbleAttachment = cb =>
|
|
||||||
Hint(".attachments .thumb", a => cb(a.src.replace("/thumbnail/", "/")))
|
|
||||||
|
|
||||||
mapsitekeys("dribbble.com", [
|
|
||||||
["s", "Heart Shot", Hint(".toggle-fav, .like-shot")],
|
|
||||||
["a", "View shot", Hint(".dribbble-over, .gif-target, .more-thumbs a")],
|
|
||||||
["A", "View shot", Hint(".dribbble-over, .gif-target, .more-thumbs a")],
|
|
||||||
["v", "View attachment image", dribbbleAttachment(a => tabOpenLink(a))],
|
|
||||||
["V", "Yank attachment image source URL", dribbbleAttachment(a => Clipboard.write(a))],
|
|
||||||
["z", "Zoom shot", Hint(".single-img picture, .detail-shot img")],
|
|
||||||
])
|
|
||||||
|
|
||||||
const behanceAddToCollection = () => document.querySelector(".qa-action-collection").click()
|
|
||||||
|
|
||||||
mapsitekeys("behance.net", [
|
|
||||||
["s", "Appreciate project", Hint(".appreciation-button")],
|
|
||||||
["b", "Add project to collection", behanceAddToCollection],
|
|
||||||
["a", "View project", Hint(".rf-project-cover__title")],
|
|
||||||
["A", "View project", Hint(".rf-project-cover__title")],
|
|
||||||
])
|
|
||||||
|
|
||||||
const wpToggleSimple = () => {
|
|
||||||
window.location.hostname = window.location.hostname.split(".")
|
|
||||||
.map((s, i) => {
|
|
||||||
if (i === 0) {
|
|
||||||
return s === "simple" ? "" : "simple"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}).filter(s => s !== "").join(".")
|
|
||||||
}
|
|
||||||
|
|
||||||
mapsitekeys("wikipedia.org", [
|
|
||||||
["s", "Toggle simple version of current article", wpToggleSimple],
|
|
||||||
])
|
|
||||||
|
|
||||||
// ---- Search & completion ----//
|
|
||||||
// Search leader
|
|
||||||
const sl = "a"
|
|
||||||
|
|
||||||
// Register Search Engine Completions
|
|
||||||
// The `completions` variable is defined in `completions.js` and
|
|
||||||
// is prepended to this file by gulp-concat.
|
|
||||||
Object.keys(completions).forEach((k) => {
|
|
||||||
const s = completions[k] // Search Engine object
|
|
||||||
const la = sl + s.alias // Search leader + alias
|
|
||||||
|
|
||||||
addSearchAliasX(s.alias, s.name, s.search, sl, s.compl, s.callback)
|
|
||||||
mapkey(la, `#8Search ${s.name}`, () => Front.openOmnibar({ type: "SearchEngine", extra: s.alias }))
|
|
||||||
})
|
|
||||||
|
|
||||||
// vim: set ft=javascript expandtab:
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ const { spawn } = require("child_process")
|
||||||
const { URL } = require("url")
|
const { URL } = require("url")
|
||||||
|
|
||||||
const paths = {
|
const paths = {
|
||||||
scripts: ["conf.priv.js", "completions.js", "conf.js"],
|
scripts: ["conf.priv.js", "completions.js", "conf.js", "actions.js", "help.js", "keys.js", "util.js"],
|
||||||
entry: "conf.js",
|
entry: "conf.js",
|
||||||
gulpfile: ["gulpfile.js"],
|
gulpfile: ["gulpfile.js"],
|
||||||
readme: ["README.tmpl.md"],
|
readme: ["README.tmpl.md"],
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Surfingkeys help categories
|
||||||
|
module.exports.categories = {
|
||||||
|
help: 0,
|
||||||
|
mouseClick: 1,
|
||||||
|
scroll: 2,
|
||||||
|
tabs: 3,
|
||||||
|
pageNav: 4,
|
||||||
|
sessions: 5,
|
||||||
|
searchSelectedWith: 6,
|
||||||
|
clipboard: 7,
|
||||||
|
omnibar: 8,
|
||||||
|
visualMode: 9,
|
||||||
|
vimMarks: 10,
|
||||||
|
settings: 11,
|
||||||
|
chromeURLs: 12,
|
||||||
|
proxy: 13,
|
||||||
|
misc: 14,
|
||||||
|
insertMode: 15,
|
||||||
|
}
|
|
@ -0,0 +1,442 @@
|
||||||
|
const actions = require("./actions")
|
||||||
|
const { categories } = require("./help")
|
||||||
|
|
||||||
|
// Remove undesired default mappings
|
||||||
|
const unmaps = {
|
||||||
|
mappings: [
|
||||||
|
"sb", "sw", "ob",
|
||||||
|
"ow", "cp", ";cp",
|
||||||
|
";ap", "spa", "spb",
|
||||||
|
"spd", "sps", "spc",
|
||||||
|
"spi", "sfr", "zQ",
|
||||||
|
"zz", "zR", "ab",
|
||||||
|
"Q", "q", "ag",
|
||||||
|
"af", ";s", "yp",
|
||||||
|
],
|
||||||
|
searchAliases: {
|
||||||
|
s: ["g", "d", "b",
|
||||||
|
"w", "s", "h"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const maps = {
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
alias: "w",
|
||||||
|
map: "k",
|
||||||
|
category: categories.scroll,
|
||||||
|
description: "Scroll up",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
map: "j",
|
||||||
|
category: categories.scroll,
|
||||||
|
description: "Scroll down",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "gi",
|
||||||
|
category: categories.pageNav,
|
||||||
|
description: "Edit current URL with vim editor",
|
||||||
|
callback: actions.vimEditURL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "gi",
|
||||||
|
category: categories.pageNav,
|
||||||
|
description: "Edit current URL with vim editor",
|
||||||
|
callback: actions.vimEditURL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "gI",
|
||||||
|
category: categories.pageNav,
|
||||||
|
description: "View image in new tab",
|
||||||
|
callback: actions.createHint("img", i => tabOpenLink(i.src)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "yp",
|
||||||
|
category: categories.clipboard,
|
||||||
|
description: "Copy URL path of current page",
|
||||||
|
callback: actions.copyURLPath(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "yI",
|
||||||
|
category: categories.clipboard,
|
||||||
|
description: "Copy Image URL",
|
||||||
|
callback: actions.createHint("img", i => Clipboard.write(i.src)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: ";se",
|
||||||
|
category: categories.settings,
|
||||||
|
description: "Edit Settings",
|
||||||
|
callback: actions.editSettings,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "gS",
|
||||||
|
category: categories.chromeURLs,
|
||||||
|
description: "Open Chrome settings",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "=w",
|
||||||
|
category: categories.misc,
|
||||||
|
description: "Lookup whois information for domain",
|
||||||
|
callback: actions.showWhois,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "=d",
|
||||||
|
category: categories.misc,
|
||||||
|
description: "Lookup dns information for domain",
|
||||||
|
callback: actions.showDns(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "=D",
|
||||||
|
category: categories.misc,
|
||||||
|
description: "Lookup all information for domain",
|
||||||
|
callback: actions.showDns({ verbose: true }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: ";pd",
|
||||||
|
category: categories.misc,
|
||||||
|
description: "Toggle PDF viewer from SurfingKeys",
|
||||||
|
callback: actions.togglePdfViewer,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"amazon.com": [
|
||||||
|
{
|
||||||
|
alias: "fs",
|
||||||
|
description: "Fakespot",
|
||||||
|
callback: actions.fakeSpot,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"google.com": [
|
||||||
|
{
|
||||||
|
alias: "a",
|
||||||
|
description: "Open search result",
|
||||||
|
callback: actions.createHint(".r>a"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "A",
|
||||||
|
description: "Open search result (new tab)",
|
||||||
|
callback: actions.createHint(".r>a", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
"yelp.com": [
|
||||||
|
{
|
||||||
|
alias: "fs",
|
||||||
|
description: "Fakespot",
|
||||||
|
callback: actions.fakeSpot,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"youtube.com": [
|
||||||
|
{
|
||||||
|
leader: "",
|
||||||
|
alias: "A",
|
||||||
|
description: "Open video",
|
||||||
|
callback: actions.createHint("*[id='video-title']", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leader: "",
|
||||||
|
alias: "C",
|
||||||
|
description: "Open channel",
|
||||||
|
callback: actions.createHint("*[id='byline']"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leader: "",
|
||||||
|
alias: "gH",
|
||||||
|
description: "Goto homepage",
|
||||||
|
callback: () => window.location.assign("https://www.youtube.com/feed/subscriptions?flow=2"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leader: "",
|
||||||
|
alias: "F",
|
||||||
|
description: "Toggle fullscreen",
|
||||||
|
callback: () => document.querySelector(".ytp-fullscreen-button.ytp-button").click(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
leader: "",
|
||||||
|
alias: "<Space>",
|
||||||
|
description: "Play/pause",
|
||||||
|
callback: actions.createHint(".ytp-play-button"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"vimeo.com": [
|
||||||
|
{
|
||||||
|
alias: "F",
|
||||||
|
description: "Toggle fullscreen",
|
||||||
|
callback: () => document.querySelector(".fullscreen-icon").click(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"github.com": [
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Toggle Star",
|
||||||
|
callback: actions.gh.star({ toggle: true }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "S",
|
||||||
|
description: "Check Star",
|
||||||
|
callback: actions.gh.star({ toggle: false }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "y",
|
||||||
|
description: "Copy Project Path",
|
||||||
|
callback: actions.copyURLPath({ count: 2 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "Y",
|
||||||
|
description: "Copy Project Path (including domain)",
|
||||||
|
callback: actions.copyURLPath({ count: 2, domain: true }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "D",
|
||||||
|
description: "View GoDoc for Project",
|
||||||
|
callback: actions.viewGodoc,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"gitlab.com": [
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Toggle Star",
|
||||||
|
callback: actions.gl.star,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "y",
|
||||||
|
description: "Copy Project Path",
|
||||||
|
callback: actions.copyURLPath({ count: 2 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "Y",
|
||||||
|
description: "Copy Project Path (including domain)",
|
||||||
|
callback: actions.copyURLPath({ count: 2, domain: true }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "D",
|
||||||
|
description: "View GoDoc for Project",
|
||||||
|
callback: actions.viewGodoc,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"twitter.com": [
|
||||||
|
{
|
||||||
|
alias: "f",
|
||||||
|
description: "Follow user",
|
||||||
|
callback: actions.createHint(".follow-button"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Like tweet",
|
||||||
|
callback: actions.createHint(".js-actionFavorite"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "R",
|
||||||
|
description: "Retweet",
|
||||||
|
callback: actions.createHint(".js-actionRetweet"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "c",
|
||||||
|
description: "Comment/Reply",
|
||||||
|
callback: actions.createHint(".js-actionReply"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "t",
|
||||||
|
description: "New tweet",
|
||||||
|
callback: actions.createHint(".js-global-new-tweet"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "T",
|
||||||
|
description: "Tweet to",
|
||||||
|
callback: actions.createHint(".NewTweetButton"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "r",
|
||||||
|
description: "Load new tweets",
|
||||||
|
callback: actions.createHint(".new-tweets-bar"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "g",
|
||||||
|
description: "Goto user",
|
||||||
|
callback: actions.createHint(".js-user-profile-link"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"reddit.com": [
|
||||||
|
{
|
||||||
|
alias: "x",
|
||||||
|
description: "Collapse comment",
|
||||||
|
callback: actions.createHint(".expand"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "X",
|
||||||
|
description: "Collapse next comment",
|
||||||
|
callback: actions.re.collapseNextComment,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Upvote",
|
||||||
|
callback: actions.createHint(".arrow.up"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "S",
|
||||||
|
description: "Downvote",
|
||||||
|
callback: actions.createHint(".arrow.down"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "e",
|
||||||
|
description: "Expand expando",
|
||||||
|
callback: actions.createHint(".expando-button"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "a",
|
||||||
|
description: "View post (link)",
|
||||||
|
callback: actions.createHint(".title"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "A",
|
||||||
|
description: "View post (link) (new tab)",
|
||||||
|
callback: actions.createHint(".title", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "c",
|
||||||
|
description: "View post (comments)",
|
||||||
|
callback: actions.createHint(".comments"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "C",
|
||||||
|
description: "View post (comments) (new tab)",
|
||||||
|
callback: actions.createHint(".comments", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"news.ycombinator.com": [
|
||||||
|
{
|
||||||
|
alias: "x",
|
||||||
|
description: "Collapse comment",
|
||||||
|
callback: actions.createHint(".togg"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "X",
|
||||||
|
description: "Collapse next comment",
|
||||||
|
callback: actions.hn.collapseNextComment,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Upvote",
|
||||||
|
callback: actions.createHint(".votearrow[title='upvote']"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "S",
|
||||||
|
description: "Downvote",
|
||||||
|
callback: actions.createHint(".votearrow[title='downvote']"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "a",
|
||||||
|
description: "View post (link)",
|
||||||
|
callback: actions.createHint(".storylink"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "A",
|
||||||
|
description: "View post (link) (new tab)",
|
||||||
|
callback: actions.createHint(".storylink", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "c",
|
||||||
|
description: "View post (comments)",
|
||||||
|
callback: actions.createHint("td > a[href*='item']:not(.storylink)"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "C",
|
||||||
|
description: "View post (comments) (new tab)",
|
||||||
|
callback: actions.createHint("td > a[href*='item']:not(.storylink)", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "p",
|
||||||
|
description: "Go to parent",
|
||||||
|
callback: actions.hn.goParent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"dribbble.com": [
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Heart Shot",
|
||||||
|
callback: actions.createHint(".toggle-fav, .like-shot"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "a",
|
||||||
|
description: "View shot",
|
||||||
|
callback: actions.createHint(".dribbble-over, .gif-target, .more-thumbs a"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "A",
|
||||||
|
description: "View shot (new tab)",
|
||||||
|
callback: actions.createHint(".dribbble-over, .gif-target, .more-thumbs a", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "v",
|
||||||
|
description: "View attachment image",
|
||||||
|
callback: actions.dr.attachment(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "V",
|
||||||
|
description: "Yank attachment image source URL",
|
||||||
|
callback: actions.dr.attachment(a => Clipboard.write(a)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "z",
|
||||||
|
description: "Zoom shot",
|
||||||
|
callback: actions.createHint(".single-img picture, .detail-shot img"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"behance.net": [
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Appreciate project",
|
||||||
|
callback: actions.createHint(".appreciation-button"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "b",
|
||||||
|
description: "Add project to collection",
|
||||||
|
callback: () => document.querySelector(".qa-action-collection").click(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "a",
|
||||||
|
description: "View project",
|
||||||
|
callback: actions.createHint(".rf-project-cover__title"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "A",
|
||||||
|
description: "View project (new tab)",
|
||||||
|
callback: actions.createHint(".rf-project-cover__title", actions.open({ newTab: true })),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"fonts.adobe.com": [
|
||||||
|
{
|
||||||
|
alias: "a",
|
||||||
|
description: "Activate font",
|
||||||
|
callback: actions.createHint(".spectrum-ToggleSwitch-input"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Favorite font",
|
||||||
|
callback: actions.createHint(".favorite-toggle-icon"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"wikipedia.org": [
|
||||||
|
{
|
||||||
|
alias: "s",
|
||||||
|
description: "Toggle simple version of current article",
|
||||||
|
callback: actions.wp.toggleSimple,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { unmaps, maps }
|
86
util.js
86
util.js
|
@ -1,4 +1,39 @@
|
||||||
const isRectVisibleInViewport = rect => (
|
const { categories } = require("./help")
|
||||||
|
|
||||||
|
const util = {}
|
||||||
|
|
||||||
|
util.escape = str => String(str).replace(/[&<>"'`=/]/g, s => ({
|
||||||
|
"&": "&",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
"\"": """,
|
||||||
|
"'": "'",
|
||||||
|
"/": "/",
|
||||||
|
"`": "`",
|
||||||
|
"=": "=",
|
||||||
|
}[s]))
|
||||||
|
|
||||||
|
util.createSuggestionItem = (html, props = {}) => {
|
||||||
|
const li = document.createElement("li")
|
||||||
|
li.innerHTML = html
|
||||||
|
return { html: li.outerHTML, props }
|
||||||
|
}
|
||||||
|
|
||||||
|
util.createURLItem = (title, url, sanitize = true) => {
|
||||||
|
let t = title
|
||||||
|
let u = url
|
||||||
|
if (sanitize) {
|
||||||
|
t = util.escape(t)
|
||||||
|
u = new URL(u).toString()
|
||||||
|
}
|
||||||
|
return util.createSuggestionItem(`
|
||||||
|
<div class="title">${t}</div>
|
||||||
|
<div class="url">${u}</div>
|
||||||
|
`, { url: u })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if the given rect is visible in the viewport
|
||||||
|
util.isRectVisibleInViewport = rect => (
|
||||||
rect.height > 0 &&
|
rect.height > 0 &&
|
||||||
rect.width > 0 &&
|
rect.width > 0 &&
|
||||||
rect.bottom >= 0 &&
|
rect.bottom >= 0 &&
|
||||||
|
@ -7,6 +42,51 @@ const isRectVisibleInViewport = rect => (
|
||||||
rect.left <= (window.innerWidth || document.documentElement.clientWidth)
|
rect.left <= (window.innerWidth || document.documentElement.clientWidth)
|
||||||
)
|
)
|
||||||
|
|
||||||
const isElementInViewport = e => isRectVisibleInViewport(e.getBoundingClientRect())
|
// Determine if the given element is visible in the viewport
|
||||||
|
util.isElementInViewport = e => util.isRectVisibleInViewport(e.getBoundingClientRect())
|
||||||
|
|
||||||
module.exports = { isRectVisibleInViewport, isElementInViewport }
|
// Process Unmaps
|
||||||
|
util.rmMaps = a => a.forEach(u => unmap(u))
|
||||||
|
|
||||||
|
util.rmSearchAliases = a => Object.entries(a).forEach(([leader, items]) =>
|
||||||
|
items.forEach(v =>
|
||||||
|
removeSearchAliasX(v, leader)))
|
||||||
|
|
||||||
|
// Process Mappings
|
||||||
|
util.processMaps = (maps, siteleader) =>
|
||||||
|
Object.entries(maps).forEach(([domain, domainMaps]) =>
|
||||||
|
domainMaps.forEach(((mapObj) => {
|
||||||
|
const {
|
||||||
|
alias,
|
||||||
|
callback,
|
||||||
|
leader = (domain === "global") ? "" : siteleader,
|
||||||
|
category = categories.misc,
|
||||||
|
description = "",
|
||||||
|
} = mapObj
|
||||||
|
const opts = {}
|
||||||
|
|
||||||
|
|
||||||
|
const key = `${leader}${alias}`
|
||||||
|
|
||||||
|
// Determine if it's a site-specific mapping
|
||||||
|
if (domain !== "global") {
|
||||||
|
const d = domain.replace(".", "\\.")
|
||||||
|
opts.domain = new RegExp(`^http(s)?://(([a-zA-Z0-9-_]+\\.)*)(${d})(/.*)?`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullDescription = `#${category} ${description}`
|
||||||
|
|
||||||
|
if (mapObj.map !== undefined) {
|
||||||
|
map(alias, mapObj.map)
|
||||||
|
} else {
|
||||||
|
mapkey(key, fullDescription, callback, opts)
|
||||||
|
}
|
||||||
|
})))
|
||||||
|
|
||||||
|
// process completions
|
||||||
|
util.processCompletions = (completions, searchleader) => Object.values(completions).forEach((s) => {
|
||||||
|
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 }))
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = util
|
||||||
|
|
Loading…
Reference in New Issue