mirror of
https://github.com/huhu/rust-search-extension
synced 2024-11-14 23:57:07 +00:00
Add CrateSearch code
This commit is contained in:
parent
591640129d
commit
e945c3cd29
2 changed files with 113 additions and 0 deletions
111
extension/crate-search.js
Normal file
111
extension/crate-search.js
Normal file
|
@ -0,0 +1,111 @@
|
|||
var levenshtein_row2 = [];
|
||||
|
||||
function levenshtein(s1, s2) {
|
||||
if (s1 === s2) {
|
||||
return 0;
|
||||
}
|
||||
var s1_len = s1.length, s2_len = s2.length;
|
||||
if (s1_len && s2_len) {
|
||||
var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
|
||||
while (i1 < s1_len) {
|
||||
row[i1] = ++i1;
|
||||
}
|
||||
while (i2 < s2_len) {
|
||||
c2 = s2.charCodeAt(i2);
|
||||
a = i2;
|
||||
++i2;
|
||||
b = i2;
|
||||
for (i1 = 0; i1 < s1_len; ++i1) {
|
||||
c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
|
||||
a = row[i1];
|
||||
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
|
||||
row[i1] = b;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
return s1_len + s2_len;
|
||||
}
|
||||
|
||||
// Prototype function to perform levenshtein contain search.
|
||||
String.prototype.levenshteinContains = function(keyword) {
|
||||
let len = keyword.length;
|
||||
if (this === keyword) return true;
|
||||
|
||||
for (let i = 0; i <= this.length - len; i++) {
|
||||
if (levenshtein(this.substring(i, len), keyword) <= 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
function cleanMinifiedUrl(rawUrl) {
|
||||
if (rawUrl === null) return null;
|
||||
return "https://" + rawUrl
|
||||
.replace("D/", "docs.rs/")
|
||||
.replace("C/", "crates.io/")
|
||||
.replace("O/", "github.io/")
|
||||
.replace("G/", "github.com/");
|
||||
}
|
||||
|
||||
// Clean the raw crate index.
|
||||
function cleanCrateIndex(rawCrateIndex) {
|
||||
let crateIndex = {};
|
||||
for (let [crateId, crate] of Object.entries(rawCrateIndex)) {
|
||||
crateIndex[crateId] = {
|
||||
id: crate.i,
|
||||
description: crate.d,
|
||||
documentation: cleanMinifiedUrl(crate.o),
|
||||
homepage: cleanMinifiedUrl(crate.h),
|
||||
repository: cleanMinifiedUrl(crate.r),
|
||||
downloads: crate.x,
|
||||
version: crate.v,
|
||||
}
|
||||
}
|
||||
return crateIndex;
|
||||
}
|
||||
|
||||
function CrateSearch(crateIndex) {
|
||||
this.crateIndex = cleanCrateIndex(crateIndex);
|
||||
this.crateIds = Object.keys(crateIndex).sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform prefix levenshtein search.
|
||||
* @param keyword the keyword to search against.
|
||||
* @param limit the max result length, default is 5.
|
||||
* @returns
|
||||
*/
|
||||
CrateSearch.prototype.search = function(keyword, limit = 5) {
|
||||
keyword = keyword.replace(/[-_]/ig, "");
|
||||
let result = [];
|
||||
for (let rawCrateId of this.crateIds) {
|
||||
let crateId = rawCrateId.replace(/[-_]/ig, "");
|
||||
if (crateId.length < keyword.length) continue;
|
||||
|
||||
let index = crateId.indexOf(keyword);
|
||||
if (index !== -1) {
|
||||
result.push({
|
||||
id: rawCrateId,
|
||||
matchIndex: index,
|
||||
});
|
||||
} else if (keyword.length >= 3 && crateId.levenshteinContains(keyword)) {
|
||||
result.push({
|
||||
id: rawCrateId,
|
||||
matchIndex: 999, // Levenshtein contain result always has lowest matchIndex.
|
||||
});
|
||||
}
|
||||
}
|
||||
// Sort the result, the lower matchIndex and length, the higher rank.
|
||||
return result.sort((a, b) => {
|
||||
if (a.matchIndex === b.matchIndex) {
|
||||
return a.id.length - b.id.length;
|
||||
}
|
||||
return a.matchIndex - b.matchIndex;
|
||||
})
|
||||
.slice(0, limit)
|
||||
.map(item => {
|
||||
return this.crateIndex[item.id];
|
||||
});
|
||||
};
|
|
@ -127,6 +127,8 @@ function buildQuery(raw) {
|
|||
var matches, type, query;
|
||||
query = raw;
|
||||
|
||||
// let query = "fn:unwrap";
|
||||
// then the matches is ["fn:", "fn", index: 0, input: "fn:unwrap", groups: undefined]
|
||||
matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
|
||||
if (matches) {
|
||||
type = matches[1].replace(/^const$/, 'constant');
|
||||
|
|
Loading…
Reference in a new issue