mirror of
https://github.com/huhu/rust-search-extension
synced 2024-11-14 15:47:12 +00:00
fix docs.rs show features (#209)
* use crates.io to get deps info * fix empty features * update permissions, show features, remove tests/script-lib.spec.js
This commit is contained in:
parent
a73754bba8
commit
b578fd882a
4 changed files with 31 additions and 104 deletions
|
@ -114,10 +114,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function enhanceFeatureFlagsMenu(menu) {
|
async function enhanceFeatureFlagsMenu(menu) {
|
||||||
|
if (crateVersion === 'latest') {
|
||||||
|
crateVersion = parseCrateVersionFromDOM();
|
||||||
|
}
|
||||||
// Use rawCrateName to fetch the Cargo.toml, otherwise will get 404.
|
// Use rawCrateName to fetch the Cargo.toml, otherwise will get 404.
|
||||||
let cargoTomUrl = `https://docs.rs/crate/${rawCrateName}/${crateVersion}/source/Cargo.toml`;
|
let cargoTomUrl = `https://docs.rs/crate/${rawCrateName}/${crateVersion}/source/Cargo.toml`;
|
||||||
let response = await fetch(cargoTomUrl);
|
let crateAPIURL = `https://crates.io/api/v1/crates/${rawCrateName}/${crateVersion}`;
|
||||||
let content = await response.text();
|
let response = await fetch(crateAPIURL);
|
||||||
|
let content = await response.json();
|
||||||
let features = parseCargoFeatures(content);
|
let features = parseCargoFeatures(content);
|
||||||
let html = `<div style="padding: 1rem"><p>
|
let html = `<div style="padding: 1rem"><p>
|
||||||
This crate has no explicit-declared feature flag.
|
This crate has no explicit-declared feature flag.
|
||||||
|
@ -141,7 +145,10 @@ async function enhanceFeatureFlagsMenu(menu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render optional dependency list.
|
// Render optional dependency list.
|
||||||
let optionalDependencies = parseOptionalDependencies(content);
|
let depsURL = `https://crates.io/api/v1/crates/${rawCrateName}/${crateVersion}/dependencies`;
|
||||||
|
let depsResponse = await fetch(depsURL);
|
||||||
|
let depsContent = await depsResponse.json();
|
||||||
|
let optionalDependencies = parseOptionalDependencies(depsContent);
|
||||||
let dependeciesList = optionalDependencies.map(dependency => `
|
let dependeciesList = optionalDependencies.map(dependency => `
|
||||||
<li class="optional-dependency-item">
|
<li class="optional-dependency-item">
|
||||||
<a href="https://docs.rs/${dependency}">
|
<a href="https://docs.rs/${dependency}">
|
||||||
|
@ -249,4 +256,4 @@ window.addEventListener("message", async function (event) {
|
||||||
insertAddToExtensionElement(getState(message.crateVersion));
|
insertAddToExtensionElement(getState(message.crateVersion));
|
||||||
console.log("Congrats! This crate has been installed successfully!");
|
console.log("Congrats! This crate has been installed successfully!");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ function isRustDoc() {
|
||||||
return gen && gen.getAttribute('content') === 'rustdoc';
|
return gen && gen.getAttribute('content') === 'rustdoc';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since this PR (https://github.com/rust-lang/docs.rs/pull/1527) merged,
|
// Since this PR (https://github.com/rust-lang/docs.rs/pull/1527) merged,
|
||||||
// the latest version path has changed:
|
// the latest version path has changed:
|
||||||
// from https://docs.rs/tokio/1.14.0/tokio/ to https://docs.rs/tokio/latest/tokio/
|
// from https://docs.rs/tokio/1.14.0/tokio/ to https://docs.rs/tokio/latest/tokio/
|
||||||
//
|
//
|
||||||
|
@ -13,7 +13,7 @@ function isRustDoc() {
|
||||||
function parseCrateVersionFromDOM() {
|
function parseCrateVersionFromDOM() {
|
||||||
let versionText = document.querySelector('form .crate-name>.title').textContent;
|
let versionText = document.querySelector('form .crate-name>.title').textContent;
|
||||||
if (versionText) {
|
if (versionText) {
|
||||||
// The form of versionText is {crateName}-{version}, separated by hypen, e.g. 'tokio-1.7.0',
|
// The form of versionText is {crateName}-{version}, separated by hypen, e.g. 'tokio-1.7.0',
|
||||||
// However, the crate name could contains hypen too, such as 'tracing-subscriber-0.3.9'.
|
// However, the crate name could contains hypen too, such as 'tracing-subscriber-0.3.9'.
|
||||||
let lastHypenIndex = versionText.lastIndexOf('-');
|
let lastHypenIndex = versionText.lastIndexOf('-');
|
||||||
return versionText.substring(lastHypenIndex + 1);
|
return versionText.substring(lastHypenIndex + 1);
|
||||||
|
@ -23,19 +23,20 @@ function parseCrateVersionFromDOM() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCargoFeatures(content) {
|
function parseCargoFeatures(content) {
|
||||||
|
if (!content.version?.features) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
let features = [];
|
let features = [];
|
||||||
|
|
||||||
let start = content.lastIndexOf("[features]");
|
function to_string(flags) {
|
||||||
if (start !== -1) {
|
return "[" + flags.map(i => '"' + i.toString() + '"').join(', ') + "]"
|
||||||
let lines = content.slice(start + "[features]\n".length).split("\n");
|
}
|
||||||
for (let line of lines) {
|
|
||||||
if (/.* = \[.*]/g.test(line)) {
|
for (const [name, flags] of Object.entries(content.version.features)) {
|
||||||
let [name, flags] = line.split("=");
|
if (name === "default") {
|
||||||
flags = flags.trim().replace(/"/ig, "");
|
features.unshift([name, to_string(flags)]);
|
||||||
features.push([name.trim(), flags]);
|
} else {
|
||||||
} else {
|
features.push([name, to_string(flags)]);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return features;
|
return features;
|
||||||
|
@ -43,29 +44,17 @@ function parseCargoFeatures(content) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse optional dependecies from Cargo.tom HTML page.
|
* Parse optional dependecies from Cargo.tom HTML page.
|
||||||
*
|
*
|
||||||
* @param {*} content HTML page of Cargo.toml content
|
* @param {*} content HTML page of Cargo.toml content
|
||||||
* @returns the list of optional dependencies
|
* @returns the list of optional dependencies
|
||||||
*/
|
*/
|
||||||
function parseOptionalDependencies(content) {
|
function parseOptionalDependencies(content) {
|
||||||
let dependencies = [];
|
let dependencies = [];
|
||||||
let start = content.indexOf("[dependencies.");
|
for (let dep of content.dependencies) {
|
||||||
if (start !== -1) {
|
if (dep.optional) {
|
||||||
let lines = content.slice(start).split("\n");
|
dependencies.push(dep.crate_id);
|
||||||
let currentCrate = null;
|
|
||||||
for (let line of lines) {
|
|
||||||
let match = line.match(/\[dependencies\.(.+)]/);
|
|
||||||
if (match) {
|
|
||||||
currentCrate = match[1];
|
|
||||||
} else if (currentCrate && /optional = true/g.test(line)) {
|
|
||||||
dependencies.push(currentCrate);
|
|
||||||
currentCrate = null;
|
|
||||||
} else if (line.startsWith("[dev-dependencies.")) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dependencies;
|
return dependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,4 +70,4 @@ function injectScripts(paths) {
|
||||||
}).forEach(script => {
|
}).forEach(script => {
|
||||||
document.body.insertAdjacentElement('beforeBegin', script);
|
document.body.insertAdjacentElement('beforeBegin', script);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ else
|
||||||
|
|
||||||
local INDEX_MANAGER_FILES = ['core/storage.js', 'index-manager.js'];
|
local INDEX_MANAGER_FILES = ['core/storage.js', 'index-manager.js'];
|
||||||
json.addIcons(icons())
|
json.addIcons(icons())
|
||||||
.addPermissions(['storage', 'unlimitedStorage'])
|
.addPermissions(['storage', 'unlimitedStorage', '*://crates.io/api/v1/crates/*'])
|
||||||
.setOptionsUi('manage/index.html')
|
.setOptionsUi('manage/index.html')
|
||||||
.addContentScript(
|
.addContentScript(
|
||||||
matches=['*://docs.rs/*'],
|
matches=['*://docs.rs/*'],
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
describe("Script library function", function() {
|
|
||||||
describe(".parseCargoFeatures()", async function() {
|
|
||||||
let inputs = [
|
|
||||||
[`<div><pre><code>
|
|
||||||
[features]
|
|
||||||
rt = ["stm32f30x-hal/rt"]
|
|
||||||
</code></pre></div>`,
|
|
||||||
[["rt", "["stm32f30x-hal/rt"]"]]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
[features]
|
|
||||||
rt = ["stm32f30x-hal/rt"]
|
|
||||||
|
|
||||||
</code></pre></div>`,
|
|
||||||
[["rt", "["stm32f30x-hal/rt"]"]]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
</code></pre></div>`,
|
|
||||||
[]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
[features]
|
|
||||||
</code></pre></div>`,
|
|
||||||
[]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
[package]
|
|
||||||
authors = ""
|
|
||||||
</code></pre></div>`,
|
|
||||||
[]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
[features]
|
|
||||||
tls = ["sqlx-core/tls"]
|
|
||||||
uuid = ["sqlx-core/uuid", "sqlx-macros/uuid"]
|
|
||||||
</code></pre></div>`,
|
|
||||||
[["tls", "["sqlx-core/tls"]"], ["uuid", "["sqlx-core/uuid", "sqlx-macros/uuid"]"]]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
[features]
|
|
||||||
tls = ["sqlx-core/tls"]
|
|
||||||
uuid = ["sqlx-core/uuid", "sqlx-macros/uuid"]
|
|
||||||
|
|
||||||
[package]
|
|
||||||
authors = []
|
|
||||||
</code></pre></div>`,
|
|
||||||
[["tls", "["sqlx-core/tls"]"], ["uuid", "["sqlx-core/uuid", "sqlx-macros/uuid"]"]]
|
|
||||||
],
|
|
||||||
[`<div><pre><code>
|
|
||||||
[features]
|
|
||||||
tls = ["sqlx-core/tls"]
|
|
||||||
uuid = ["sqlx-core/uuid", "sqlx-macros/uuid"]
|
|
||||||
default = []
|
|
||||||
|
|
||||||
[package]
|
|
||||||
authors = ""
|
|
||||||
</code></pre></div>`,
|
|
||||||
[["tls", "["sqlx-core/tls"]"], ["uuid", "["sqlx-core/uuid", "sqlx-macros/uuid"]"], ["default", "[]"]]
|
|
||||||
],
|
|
||||||
];
|
|
||||||
inputs.forEach(([content, expected], number) => {
|
|
||||||
it(`Parse crate feature flags #${number}`, function() {
|
|
||||||
let features = parseCargoFeatures(content);
|
|
||||||
features.should.has.lengthOf(expected.length);
|
|
||||||
features.should.deep.equal(expected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in a new issue