Skip to content

Instantly share code, notes, and snippets.

@hytor-yang
Last active April 2, 2024 03:31
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save hytor-yang/6e8cf7f3f45cc6ba598f0c20ea9fa383 to your computer and use it in GitHub Desktop.
Save hytor-yang/6e8cf7f3f45cc6ba598f0c20ea9fa383 to your computer and use it in GitHub Desktop.
Surfingkeys customization with jd/douban/taobao search and copy tab(s) as markdown feature.
const {
aceVimMap,
mapkey,
imap,
imapkey,
insertJS,
getClickableElements,
vmapkey,
map,
unmap,
cmap,
addSearchAlias,
removeSearchAlias,
tabOpenLink,
readText,
Clipboard,
Front,
Hints,
Visual,
RUNTIME,
} = api;
/* Key Bindings */
// A VSCode convention for Tab History back/forward
map("<Ctrl-->", "B");
map("<Ctrl-_>", "F");
/* Search Alias */
// Remove Duckduckgo Search
removeSearchAlias("d");
// Add Search for JD (京东), Taobao(淘宝), Douban Book(豆瓣图书)
addSearchAlias(
"j",
"jd",
"http://search.jd.com/Search?enc=utf-8&keyword=",
"s"
);
addSearchAlias(
"tb",
"taobao",
"https://s.taobao.com/search?q=",
"s",
"https://suggest.taobao.com/sug?code=utf-8&q=",
function (response) {
var res = [];
try {
res = JSON.parse(response.text).result.map(function (it) {
return it[0];
});
} catch (e) {}
return res;
}
);
addSearchAlias(
"db",
"doubanbook",
"https://www.douban.com/search?cat=1001&q=",
"s"
);
/* Advanced Bookmark, and Page Meta Copy */
// Util to remove URL query and hash.
// ⚠️ It's so rude that some URL would break due to necessary query params missing.
// Use a well maintained URL Cleaning Extension instead. Or purify only those targets that you quite sure.
function _cleanupUrl(url, doCleanup) {
return doCleanup ? /http[^#\?]*/.exec(url)[0] : url;
}
function getAliDevopsTaskId() {
const workitemIdElSelector = "[class^=workItemTitle--idBox]"
let workitemIdEl = document.querySelector(workitemIdElSelector);
if (workitemIdEl == null) {
blinkAliDevopsWorkItemIdBox()
workitemIdEl = document.querySelector(workitemIdElSelector);
}
return workitemIdEl && workitemIdEl.innerText || '';
}
function blinkAliDevopsWorkItemIdBox() {
// Thx to [brookhong/Surfingkeys#1345](https://github.com/brookhong/Surfingkeys/issues/1345)
// insertJS is currently the only way I figured out to 'call tab page's window global API.'
insertJS(function () {
if (typeof window.aoneCallback_workitemDrawerSetHideIdShowTitle != 'function') {
console.log('Oops, Aliyun Devops priviate API aoneCallback_workitemDrawerSetHideIdShowTitle is not available...')
return
}
window.aoneCallback_workitemDrawerSetHideIdShowTitle(false)
window.setTimeout(function () {
window.aoneCallback_workitemDrawerSetHideIdShowTitle(true)
}, 200)
})
}
// Custimized Bookmark
function _getCurrentTabTitle(doCleanup) {
let title = document.title;
const url = location.href;
const urlHost = location.hostname;
const urlPath = location.pathname;
let prefix = "";
// Get actual article title for Wechat Public Account page. 获取微信公众号文章的实际标题
// You may don't need this if you are using dedicated User Script. 如果使用了专门的 User Script, 这个功能就不必要了。
// e.g. [修改微信公众号文章title标题](https://greasyfork.org/en/scripts/375439-%E4%BF%AE%E6%94%B9%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%96%87%E7%AB%A0title%E6%A0%87%E9%A2%98)
// if (urlHost === 'mp.weixin.qq.com') {
// title = document.getElementById('activity-name').innerText
// }
// For Alfred Forum. Remove suffix of 'Discussion & Help - Alfred App Community Forum'
if (urlHost.includes("www.alfredforum.com")) {
title = title.replace(
"- Discussion & Help - Alfred App Community Forum",
""
);
}
// For Zhihu. 精简私信、消息提示文字
if (urlHost.includes("www.zhihu.com")) {
title = title.replace(/\(\d+.*(消息|私信)\) /, "").replace(" - 知乎", "");
}
// For Github.
if (urlHost === "github.com") {
const issuesRegexPattern = /issues\/\d+$/;
const prRegexPattern = /pull\/\d+$/;
if (issuesRegexPattern.test(urlPath)) {
// Github issue detail page. Simplify to ${repo-name}#${issue-no}. e.g. [vitejs/vite#123](https://github.com/vitejs/vite/issues/123)
const issuePathParts = /\/(.*)\/issues\/(\d+)$/.exec(urlPath);
const [, repoName, issueNo] = issuePathParts;
title = `${repoName}#${issueNo}`;
} else if (prRegexPattern.test(urlPath)) {
// Github pull request detail page. Simplify to ${repo-name} PR #${pr-no}. e.g. [vitejs/vite PR #456](https://github.com/vitejs/vite/pull/456)
const prPathParts = /\/(.*)\/pull\/(\d+)$/.exec(urlPath);
const [, repoName, prNo] = prPathParts;
title = `${repoName} PR #${prNo}`;
} else {
// Github Repo root page. Add Stars. e.g. 61.4k★ [vitejs/vite: Next generation frontend tooling. It's fast!](https://github.com/vitejs/vite)
const starCountEl = document.querySelector("#repo-stars-counter-star");
const starCount = (starCountEl && starCountEl.innerText.trim()) || "0";
prefix =
starCount.endsWith("k") || parseInt(starCount) > 99
? `${starCount}★ `
: "";
}
}
// For Aliyun Devops, get workitem title and id. 阿里云效,获取工作项标题与 ID。
if (
urlHost === "devops.aliyun.com" &&
((urlPath.startsWith("/projex/workitem") &&
url.includes("openWorkitemIdentifier=")) ||
/projex\/project\/\w+\/(req|task)/.test(urlPath))
) {
const workitemTitleEl = document.querySelector("#workitemTitleInputBox");
title = (workitemTitleEl && workitemTitleEl.value || "") + ', ' + getAliDevopsTaskId();
}
return { prefix, title, url: _cleanupUrl(url, doCleanup) };
}
// Custimized Markdown Format Bookmark
function _getCurrentTabMarkdown(doCleanup) {
const { prefix, title, url } = _getCurrentTabTitle(doCleanup);
return `${prefix}[${title}](${url})`;
}
// Custimized Markdown Format Bookmark for All Opened Tabs.
function _copyAllTabsMarkdown(doCleanup) {
RUNTIME("getTabs", null, (response) => {
const tabs = (response && response.tabs) || [];
markdownStr = tabs
.filter(
(tab) => tab.url.startsWith("http") && tab.url.indexOf("cache") === -1
)
.map((tab) => `[${tab.title}](${_cleanupUrl(tab.url, doCleanup)})`)
.concat(_getCurrentTabMarkdown(doCleanup))
.join("\n");
Clipboard.write(markdownStr);
});
}
mapkey(
"ybb",
"Copy current tab in Markdown format",
function () {
Clipboard.write(_getCurrentTabMarkdown());
},
{}
);
mapkey(
"ybcb",
"Copy current tab in Markdown format, removing query and hash in URL",
function () {
Clipboard.write(_getCurrentTabMarkdown(true));
},
{}
);
mapkey(
"ybl",
"Copy current tab's title, with custimized transformation.",
function () {
const { title } = _getCurrentTabTitle();
Clipboard.write(title);
},
{}
);
mapkey(
"yba",
"Copy all tabs in Markdown format",
function () {
_copyAllTabsMarkdown();
},
{}
);
mapkey(
"ybca",
"Copy all tabs in Markdown format, removing query and hash in URL",
function () {
_copyAllTabsMarkdown(true);
},
{}
);
// Shared theme setting from Official SurfingKeys repo? Credit to original author
settings.theme = `
.sk_theme {
font-family: Input Sans Condensed, Charcoal, sans-serif;
font-size: 10pt;
background: #24272e;
color: #abb2bf;
}
.sk_theme tbody {
color: #fff;
}
.sk_theme input {
color: #d0d0d0;
}
.sk_theme .url {
color: #61afef;
}
.sk_theme .annotation {
color: #56b6c2;
}
.sk_theme .omnibar_highlight {
color: #528bff;
}
.sk_theme .omnibar_timestamp {
color: #e5c07b;
}
.sk_theme .omnibar_visitcount {
color: #98c379;
}
.sk_theme #sk_omnibarSearchResult>ul>li:nth-child(odd) {
background: #303030;
}
.sk_theme #sk_omnibarSearchResult>ul>li.focused {
background: #3e4452;
}
#sk_status, #sk_find {
font-size: 20pt;
}`;
// click `Save` button to make above settings to take effect.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment