rust-search-extension/extension/main.js

220 lines
7.7 KiB
JavaScript
Raw Normal View History

2020-02-24 06:18:03 +00:00
const c = new Compat();
const crateSearcher = new CrateSearch(mapping, crateIndex);
const attributeSearcher = new AttributeSearch();
2020-02-17 03:37:59 +00:00
const bookSearcher = new BookSearch(booksIndex);
2020-03-05 15:33:32 +00:00
const lintSearcher = new LintSearch(lintsIndex);
2020-03-07 09:13:18 +00:00
const stdSearcher = new StdSearch(searchIndex);
2020-03-08 02:59:37 +00:00
const crateDocSearchManager = new CrateDocSearchManager();
2020-05-18 14:59:36 +00:00
const commandManager = new CommandManager(
2020-05-18 13:35:04 +00:00
new HelpCommand(),
new BookCommand(),
new YetCommand(),
new StableCommand(),
new ToolCommand(),
new LabelCommand(labelsIndex),
2020-05-18 14:59:36 +00:00
new HistoryCommand(),
);
2020-02-10 03:58:12 +00:00
const defaultSuggestion = `Search std ${c.match("docs")}, external ${c.match("docs")} (@), ${c.match("crates")} (!), ${c.match("attributes")} (#), ${c.match("books")} (%), clippy ${c.match("lints")} (>), and ${c.match("error codes")}, etc in your address bar instantly!`;
2020-04-25 08:20:25 +00:00
const omnibox = new Omnibox(defaultSuggestion, c.omniboxPageSize());
2019-12-28 15:15:02 +00:00
let formatDoc = (index, doc) => {
2020-03-08 02:59:37 +00:00
let description = doc.displayPath + c.match(doc.name);
if (doc.desc) {
description += " - " + c.dim(c.escape(doc.desc));
}
2020-05-27 15:16:59 +00:00
return { content: doc.href, description };
2020-03-08 02:59:37 +00:00
};
2020-02-09 13:25:21 +00:00
omnibox.bootstrap({
onSearch: (query) => {
2020-03-07 09:13:18 +00:00
return stdSearcher.search(query);
2020-02-09 13:25:21 +00:00
},
onFormat: formatDoc,
2020-02-09 13:25:21 +00:00
onAppend: (query) => {
return [{
content: stdSearcher.getSearchUrl(query),
2020-03-08 02:59:37 +00:00
description: `Search Rust docs ${c.match(query)} on ${settings.isOfflineMode ? "offline mode" : stdSearcher.rootPath}`,
}];
2020-02-09 13:25:21 +00:00
},
beforeNavigate: (query, content) => {
2020-04-25 15:29:21 +00:00
if (content && /^@.\w+$/i.test(content.trim())) {
// Case: @crate, redirect to that crate's docs.rs page
2020-04-16 16:15:07 +00:00
return `https://docs.rs/${content.replace("@", "")}`;
} else if (content && /^https?.*\/~\/\*\/.*/ig.test(content)) {
// Sanitize docs url which from all crates doc search mode. (Prefix with "~")
// Here is the url instance: https://docs.rs/~/*/reqwest/fn.get.html
let [_, __, crateName] = new URL(content).pathname.slice(1).split("/");
let crateVersion = CrateDocSearchManager.getCrates()[crateName].version;
return content.replace("/~/", `/${crateName}/`).replace("/*/", `/${crateVersion}/`);
2020-04-16 16:15:07 +00:00
} else {
return content;
}
},
afterNavigated: (query, result) => {
HistoryCommand.record(query, result);
}
2020-02-09 13:25:21 +00:00
});
omnibox.addPrefixQueryEvent("~", {
onSearch: (query) => {
return crateDocSearchManager.searchAll(query);
},
onFormat: formatDoc,
});
2020-03-08 02:59:37 +00:00
omnibox.addPrefixQueryEvent("@", {
onSearch: (query) => {
return crateDocSearchManager.search(query);
},
onFormat: (index, item) => {
if (item.hasOwnProperty("content")) {
// 1. Crate list header.
// 2. Crate result footer
return item;
} else if (item.hasOwnProperty("href")) {
return formatDoc(index, item);
} else {
// Crate name list.
let content = `@${item.name}`;
return {
content,
description: `${c.match(content)} v${item.version} - ${c.dim(item.doc)}`,
}
}
},
2020-03-08 02:59:37 +00:00
});
const REDIRECT_URL = chrome.runtime.getURL("redirect/redirect.html");
2020-02-09 13:25:21 +00:00
omnibox.addPrefixQueryEvent("!", {
defaultSearch: true,
searchPriority: 1,
onSearch: (query) => {
return crateSearcher.search(query);
},
onFormat: (index, crate, query) => {
let content;
let description;
if (query.startsWith("!!!")){
content = `${REDIRECT_URL}?crate=${crate.id}`;
description = `${c.capitalize("repository")}: ${c.match(crate.id)} v${crate.version} - ${c.dim(c.escape(crate.description))}`;
} else if(query.startsWith("!!")) {
content = `https://docs.rs/${crate.id}`;
description = `${c.capitalize("docs.rs")}: ${c.match(crate.id)} v${crate.version} - ${c.dim(c.escape(crate.description))}`
} else {
content = `https://${settings.crateRegistry}/crates/${crate.id}`;
description = `${c.capitalize(settings.crateRegistry)}: ${c.match(crate.id)} v${crate.version} - ${c.dim(c.escape(crate.description))}`
}
return {
content,
description
2020-02-09 13:25:21 +00:00
};
},
onAppend: (query) => {
let keyword = query.replace(/[!\s]/g, "");
2020-02-09 13:25:21 +00:00
return [{
content: "https://crates.io/search?q=" + encodeURIComponent(keyword),
description: "Search Rust crates for " + c.match(keyword) + " on https://crates.io",
2020-02-26 10:13:21 +00:00
}, {
content: "remind",
description: `Remind: ${c.dim("We only indexed the top 20K crates. Sorry for the inconvenience if your desired crate not show.")}`,
2020-02-09 13:25:21 +00:00
}];
}
});
omnibox.addPrefixQueryEvent("#", {
defaultSearch: true,
searchPriority: 2,
2020-02-23 13:00:55 +00:00
deduplicate: true,
2020-02-09 13:25:21 +00:00
onSearch: (query) => {
return attributeSearcher.search(query);
},
onFormat: (index, attribute) => {
return {
2020-02-23 06:24:38 +00:00
content: attribute.href,
2020-02-24 06:18:03 +00:00
description: `Attribute: ${c.match("#[" + attribute.name + "]")} ${c.dim(attribute.description)}`,
2020-02-09 13:25:21 +00:00
}
}
});
omnibox.addRegexQueryEvent(/e\d{2,4}$/i, {
onSearch: (query) => {
let baseIndex = parseInt(query.slice(1).padEnd(4, '0'));
let result = [];
for (let index = 0; index < 10; index++) {
let errorIndex = 'E' + String(baseIndex++).padStart(4, "0").toUpperCase();
result.push(errorIndex);
}
return result;
},
onFormat: (index, errorCode) => {
return {
content: "https://doc.rust-lang.org/error-index.html#" + errorCode,
2020-02-24 06:18:03 +00:00
description: `Search Rust error index for ${c.match(errorCode)} on https://doc.rust-lang.org/error-index.html`,
2020-02-10 03:58:12 +00:00
};
2020-02-09 13:25:21 +00:00
}
});
2020-02-17 03:37:59 +00:00
omnibox.addPrefixQueryEvent("%", {
onSearch: (query) => {
return bookSearcher.search(query);
},
onFormat: (index, page) => {
let parentTitles = page.parentTitles || [];
2020-02-17 03:37:59 +00:00
return {
content: page.url,
2020-03-07 09:13:18 +00:00
description: `${[...parentTitles.map(t => c.escape(t)), c.match(c.escape(page.title))].join(" > ")} - ${c.dim(page.name)}`
2020-02-17 03:37:59 +00:00
}
}
});
2020-03-05 15:33:32 +00:00
const LINT_URL = "https://rust-lang.github.io/rust-clippy/master/";
omnibox.addPrefixQueryEvent(">", {
onSearch: (query) => {
return lintSearcher.search(query);
},
onFormat: (index, lint) => {
return {
content: `${LINT_URL}#${lint.name}`,
description: `Clippy lint: [${lint.level}] ${c.match(lint.name)} - ${c.dim(c.escape(lint.description))}`,
}
},
});
omnibox.addPrefixQueryEvent(":", {
onSearch: (query) => {
return commandManager.execute(query);
},
});
2020-05-01 03:46:13 +00:00
omnibox.addNoCacheQueries("!", "@", ":");
2020-04-15 15:49:44 +00:00
let fileNewIssue = "title=Have you found a bug? Did you feel something was missing?&body=Whatever it was, we'd love to hear from you.";
chrome.runtime.setUninstallURL(
`https://github.com/huhu/rust-search-extension/issues/new?${encodeURI(fileNewIssue)}`
);
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
switch (message.action) {
case "check": {
let crates = CrateDocSearchManager.getCrates();
sendResponse(crates[message.crateName]);
break;
}
case "add": {
CrateDocSearchManager.addCrate(message.crateName, message.crateVersion, message.searchIndex);
crateDocSearchManager.initAllCrateSearcher();
sendResponse(true);
break;
}
case "remove": {
CrateDocSearchManager.removeCrate(message.crateName);
crateDocSearchManager.initAllCrateSearcher();
sendResponse(true);
break;
}
}
return true;
});
window.crateSearcher = crateSearcher;