Rollup merge of #151091 - hide-deprecated-items, r=lolbinarycat

Add new "hide deprecated items" setting in rustdoc

This PR adds a new JS setting which allows the JS to hide deprecated items. This is especially useful for crates like `std` which accumulates deprecated items but never removes them.

Nicely enough, the "deprecation" information was already in the search index, meaning I didn't need to change anything there. Before this PR, it was only used to make the deprecated items rank lower. Well now it's also used to generate an extra CSS class, allowing the JS setting to work.

This is taking over https://github.com/rust-lang/rust/pull/149551.

This feature got approved by the rustdoc team in the [meeting of december](https://rust-lang.zulipchat.com/#narrow/channel/393423-t-rustdoc.2Fmeetings/topic/2025-12-08/near/562553156).

You can give it a try [here](https://rustdoc.crud.net/imperio/hide-deprecated-items/foo/index.html).

r? @lolbinarycat
This commit is contained in:
Stuart Cook
2026-01-20 18:00:09 +11:00
committed by GitHub
17 changed files with 295 additions and 83 deletions
+1
View File
@@ -126,6 +126,7 @@ fn synthesize_auto_trait_impl<'tcx>(
items: Vec::new(),
polarity,
kind: clean::ImplKind::Auto,
is_deprecated: false,
})),
item_id: clean::ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
cfg: None,
+3
View File
@@ -117,6 +117,9 @@ pub(crate) fn synthesize_blanket_impls(
None,
None,
))),
is_deprecated: tcx
.lookup_deprecation(impl_def_id)
.is_some_and(|deprecation| deprecation.is_in_effect()),
})),
cfg: None,
inline_stmt_id: None,
+3
View File
@@ -645,6 +645,9 @@ pub(crate) fn build_impl(
} else {
ImplKind::Normal
},
is_deprecated: tcx
.lookup_deprecation(did)
.is_some_and(|deprecation| deprecation.is_in_effect()),
})),
merged_attrs,
cfg,
+4
View File
@@ -2904,6 +2904,9 @@ fn clean_impl<'tcx>(
)),
_ => None,
});
let is_deprecated = tcx
.lookup_deprecation(def_id.to_def_id())
.is_some_and(|deprecation| deprecation.is_in_effect());
let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| {
let kind = ImplItem(Box::new(Impl {
safety: match impl_.of_trait {
@@ -2924,6 +2927,7 @@ fn clean_impl<'tcx>(
} else {
ImplKind::Normal
},
is_deprecated,
}));
Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, cx)
};
+8
View File
@@ -427,6 +427,10 @@ pub(crate) fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
})
}
pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
self.deprecation(tcx).is_some_and(|deprecation| deprecation.is_in_effect())
}
pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
self.item_id.as_def_id().map(|did| inner_docs(tcx.get_all_attrs(did))).unwrap_or(false)
}
@@ -1270,6 +1274,9 @@ pub(crate) fn safety(&self, tcx: TyCtxt<'_>) -> hir::Safety {
pub(crate) fn is_dyn_compatible(&self, tcx: TyCtxt<'_>) -> bool {
tcx.is_dyn_compatible(self.def_id)
}
pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
tcx.lookup_deprecation(self.def_id).is_some_and(|deprecation| deprecation.is_in_effect())
}
}
#[derive(Clone, Debug)]
@@ -2254,6 +2261,7 @@ pub(crate) struct Impl {
pub(crate) items: Vec<Item>,
pub(crate) polarity: ty::ImplPolarity,
pub(crate) kind: ImplKind,
pub(crate) is_deprecated: bool,
}
impl Impl {
+2 -2
View File
@@ -593,7 +593,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
cache,
);
let aliases = item.attrs.get_doc_aliases();
let deprecation = item.deprecation(tcx);
let is_deprecated = item.is_deprecated(tcx);
let index_item = IndexItem {
ty: item.type_(),
defid: Some(defid),
@@ -608,7 +608,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
impl_id,
search_type,
aliases,
deprecation,
is_deprecated,
};
cache.search_index.push(index_item);
+27 -8
View File
@@ -141,7 +141,7 @@ pub(crate) struct IndexItem {
pub(crate) impl_id: Option<DefId>,
pub(crate) search_type: Option<IndexItemFunctionType>,
pub(crate) aliases: Box<[Symbol]>,
pub(crate) deprecation: Option<Deprecation>,
pub(crate) is_deprecated: bool,
}
/// A type used for the search index.
@@ -1791,12 +1791,14 @@ fn doc_impl_item(
let mut info_buffer = String::new();
let mut short_documented = true;
let mut trait_item_deprecated = false;
if render_method_item {
if !is_default_item {
if let Some(t) = trait_ {
// The trait item may have been stripped so we might not
// find any documentation or stability for it.
if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
trait_item_deprecated = it.is_deprecated(cx.tcx());
// We need the stability of the item from the trait
// because impls can't have a stability.
if !item.doc_value().is_empty() {
@@ -1836,10 +1838,20 @@ fn doc_impl_item(
Either::Right(boring)
};
let mut deprecation_class = if trait_item_deprecated || item.is_deprecated(cx.tcx()) {
" deprecated"
} else {
""
};
let toggled = !doc_buffer.is_empty();
if toggled {
let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>")?;
write!(
w,
"<details class=\"toggle{method_toggle_class}{deprecation_class}\" open><summary>"
)?;
deprecation_class = "";
}
match &item.kind {
clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
@@ -1856,7 +1868,7 @@ fn doc_impl_item(
.map(|item| format!("{}.{name}", item.type_()));
write!(
w,
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}{deprecation_class}\">\
{}",
render_rightside(cx, item, render_mode)
)?;
@@ -1882,7 +1894,7 @@ fn doc_impl_item(
let id = cx.derive_id(&source_id);
write!(
w,
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}{deprecation_class}\">\
{}",
render_rightside(cx, item, render_mode)
)?;
@@ -1909,7 +1921,7 @@ fn doc_impl_item(
let id = cx.derive_id(&source_id);
write!(
w,
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}{deprecation_class}\">\
{}",
render_rightside(cx, item, render_mode),
)?;
@@ -1941,7 +1953,7 @@ fn doc_impl_item(
let id = cx.derive_id(&source_id);
write!(
w,
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}{deprecation_class}\">\
{}",
render_rightside(cx, item, render_mode),
)?;
@@ -1968,7 +1980,7 @@ fn doc_impl_item(
let id = cx.derive_id(&source_id);
write!(
w,
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
"<section id=\"{id}\" class=\"{item_type}{in_trait_class}{deprecation_class}\">\
{}",
render_rightside(cx, item, render_mode),
)?;
@@ -2140,11 +2152,18 @@ fn render_default_items(
}
if render_mode == RenderMode::Normal {
let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
let deprecation_attr = if impl_.is_deprecated
|| trait_.is_some_and(|trait_| trait_.is_deprecated(cx.tcx()))
{
" deprecated"
} else {
""
};
if toggled {
close_tags.push("</details>");
write!(
w,
"<details class=\"toggle implementors-toggle\"{}>\
"<details class=\"toggle implementors-toggle{deprecation_attr}\"{}>\
<summary>",
if rendering_params.toggle_open_by_default { " open" } else { "" }
)?;
+34 -15
View File
@@ -217,6 +217,10 @@ fn toggle_close(mut w: impl fmt::Write) {
}
fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> impl fmt::Display {
fn deprecation_class_attr(is_deprecated: bool) -> &'static str {
if is_deprecated { " class=\"deprecated\"" } else { "" }
}
fmt::from_fn(|w| {
write!(w, "{}", document(cx, item, None, HeadingOffset::H2))?;
@@ -370,11 +374,18 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
write!(w, "</code></dt>")?
}
clean::ImportItem(ref import) => {
let stab_tags =
import.source.did.map_or_else(String::new, |import_def_id| {
print_extra_info_tags(tcx, myitem, item, Some(import_def_id))
.to_string()
});
let (stab_tags, deprecation) = match import.source.did {
Some(import_def_id) => {
let stab_tags =
print_extra_info_tags(tcx, myitem, item, Some(import_def_id))
.to_string();
let deprecation = tcx
.lookup_deprecation(import_def_id)
.is_some_and(|deprecation| deprecation.is_in_effect());
(stab_tags, deprecation)
}
None => (String::new(), item.is_deprecated(tcx)),
};
let id = match import.kind {
clean::ImportKind::Simple(s) => {
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
@@ -383,8 +394,8 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
};
write!(
w,
"<dt{id}>\
<code>"
"<dt{id}{deprecation_attr}><code>",
deprecation_attr = deprecation_class_attr(deprecation)
)?;
render_attributes_in_code(w, myitem, "", cx)?;
write!(
@@ -396,9 +407,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
)?;
}
_ => {
if myitem.name.is_none() {
continue;
}
let Some(item_name) = myitem.name else { continue };
let unsafety_flag = match myitem.kind {
clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
@@ -431,9 +440,10 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
.into_string();
let (docs_before, docs_after) =
if docs.is_empty() { ("", "") } else { ("<dd>", "</dd>") };
let deprecation_attr = deprecation_class_attr(myitem.is_deprecated(tcx));
write!(
w,
"<dt>\
"<dt{deprecation_attr}>\
<a class=\"{class}\" href=\"{href}\" title=\"{title1} {title2}\">\
{name}\
</a>\
@@ -442,12 +452,12 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
{stab_tags}\
</dt>\
{docs_before}{docs}{docs_after}",
name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()),
name = EscapeBodyTextWithWbr(item_name.as_str()),
visibility_and_hidden = visibility_and_hidden,
stab_tags = print_extra_info_tags(tcx, myitem, item, None),
class = type_,
unsafety_flag = unsafety_flag,
href = print_item_path(type_, myitem.name.unwrap().as_str()),
href = print_item_path(type_, item_name.as_str()),
title1 = myitem.type_(),
title2 = full_path(cx, myitem),
)?;
@@ -778,15 +788,24 @@ fn trait_item(cx: &Context<'_>, m: &clean::Item, t: &clean::Item) -> impl fmt::D
let content = document_full(m, cx, HeadingOffset::H5).to_string();
let mut deprecation_class =
if m.is_deprecated(cx.tcx()) { " deprecated" } else { "" };
let toggled = !content.is_empty();
if toggled {
let method_toggle_class =
if item_type.is_method() { " method-toggle" } else { "" };
write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>")?;
write!(
w,
"<details \
class=\"toggle{method_toggle_class}{deprecation_class}\" \
open><summary>"
)?;
deprecation_class = "";
}
write!(
w,
"<section id=\"{id}\" class=\"method\">\
"<section id=\"{id}\" class=\"method{deprecation_class}\">\
{}\
<h4 class=\"code-header\">{}</h4></section>",
render_rightside(cx, m, RenderMode::Normal),
+2 -2
View File
@@ -1282,7 +1282,7 @@ pub(crate) fn build_index(
cache,
),
aliases: item.attrs.get_doc_aliases(),
deprecation: item.deprecation(tcx),
is_deprecated: item.is_deprecated(tcx),
});
}
}
@@ -1519,7 +1519,7 @@ pub(crate) fn build_index(
trait_parent: item.trait_parent_idx,
module_path,
exact_module_path,
deprecated: item.deprecation.is_some(),
deprecated: item.is_deprecated,
associated_item_disambiguator: if let Some(impl_id) = item.impl_id
&& let Some(parent_idx) = item.parent_idx
&& associated_item_duplicates
+10 -1
View File
@@ -64,7 +64,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
<path d="M3,5h16M3,11h16M3,17h16" stroke-width="2.75"/></svg>');
}
:root.sans-serif {
:root.sans-serif-fonts {
--font-family: "Fira Sans", sans-serif;
--font-family-code: "Fira Mono", monospace;
}
@@ -2642,6 +2642,15 @@ However, it's not needed with smaller screen width because the doc/code block is
}
}
/* Items on module pages */
.hide-deprecated-items dt.deprecated,
.hide-deprecated-items dt.deprecated + dd,
/* Items on item pages */
.hide-deprecated-items .deprecated,
.hide-deprecated-items .deprecated + .item-info {
display: none;
}
/*
WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
If you update this line, then you also need to update the line with the same warning
+3
View File
@@ -4920,6 +4920,9 @@ async function addTab(results, query, display, finishedCallback, isTypeSearch) {
const link = document.createElement("a");
link.className = "result-" + type;
if (obj.item.deprecated) {
link.className += " deprecated";
}
link.href = obj.href;
const resultName = document.createElement("span");
+11 -30
View File
@@ -43,41 +43,17 @@
}
}
break;
case "hide-sidebar":
if (value === true) {
addClass(document.documentElement, "hide-sidebar");
} else {
removeClass(document.documentElement, "hide-sidebar");
}
break;
case "hide-toc":
if (value === true) {
addClass(document.documentElement, "hide-toc");
} else {
removeClass(document.documentElement, "hide-toc");
}
break;
case "hide-modnav":
if (value === true) {
addClass(document.documentElement, "hide-modnav");
} else {
removeClass(document.documentElement, "hide-modnav");
}
break;
case "sans-serif-fonts":
if (value === true) {
addClass(document.documentElement, "sans-serif");
} else {
removeClass(document.documentElement, "sans-serif");
}
break;
case "hide-sidebar":
case "hide-toc":
case "hide-modnav":
case "word-wrap-source-code":
case "hide-deprecated-items":
if (value === true) {
addClass(document.documentElement, "word-wrap-source-code");
addClass(document.documentElement, settingName);
} else {
removeClass(document.documentElement, "word-wrap-source-code");
removeClass(document.documentElement, settingName);
}
break;
}
}
@@ -274,6 +250,11 @@
"js_name": "word-wrap-source-code",
"default": false,
},
{
"name": "Hide deprecated items",
"js_name": "hide-deprecated-items",
"default": false,
},
];
// Then we build the DOM.
+16 -15
View File
@@ -319,21 +319,22 @@ updateTheme();
if (getSettingValue("source-sidebar-show") === "true") {
addClass(document.documentElement, "src-sidebar-expanded");
}
if (getSettingValue("hide-sidebar") === "true") {
addClass(document.documentElement, "hide-sidebar");
}
if (getSettingValue("hide-toc") === "true") {
addClass(document.documentElement, "hide-toc");
}
if (getSettingValue("hide-modnav") === "true") {
addClass(document.documentElement, "hide-modnav");
}
if (getSettingValue("sans-serif-fonts") === "true") {
addClass(document.documentElement, "sans-serif");
}
if (getSettingValue("word-wrap-source-code") === "true") {
addClass(document.documentElement, "word-wrap-source-code");
}
(function() {
const settings = [
"hide-sidebar",
"hide-toc",
"hide-modnav",
"word-wrap-source-code",
"hide-deprecated-items",
"sans-serif-fonts",
];
for (const setting of settings) {
if (getSettingValue(setting) === "true") {
addClass(document.documentElement, setting);
}
}
})();
function updateSidebarWidth() {
const desktopSidebarWidth = getSettingValue("desktop-sidebar-width");
if (desktopSidebarWidth && desktopSidebarWidth !== "null") {
+2 -1
View File
@@ -711,7 +711,8 @@ fn from_clean(
impl FromClean<clean::Impl> for Impl {
fn from_clean(impl_: &clean::Impl, renderer: &JsonRenderer<'_>) -> Self {
let provided_trait_methods = impl_.provided_trait_methods(renderer.tcx);
let clean::Impl { safety, generics, trait_, for_, items, polarity, kind } = impl_;
let clean::Impl { safety, generics, trait_, for_, items, polarity, kind, is_deprecated: _ } =
impl_;
// FIXME: use something like ImplKind in JSON?
let (is_synthetic, blanket_impl) = match kind {
clean::ImplKind::Normal | clean::ImplKind::FakeVariadic => (false, None),
@@ -0,0 +1,96 @@
// Test that the "hide deprecated" setting is correctly handled.
include: "utils.goml"
go-to: "file://" + |DOC_PATH| + "/lib2/deprecated/index.html"
store-value: (deprecated_class, ".deprecated")
// There should be two deprecated items listed on the module page:
// `DeprecatedStruct` and `DeprecatedTrait`.
assert-count: ("dt" + |deprecated_class|, 2)
// `DeprecatedStruct` and `DeprecatedTrait` should be displayed for now.
assert-css: ("dt" + |deprecated_class|, {"display": "block"}, ALL)
// We enable the "hide deprecated items" setting.
call-function: ("open-settings-menu", {})
click: "#hide-deprecated-items"
// None of them should be displayed anymore.
wait-for-css: ("dt" + |deprecated_class|, {"display": "none"}, ALL)
// We disable the setting.
click: "#hide-deprecated-items"
// All of them should be displayed back.
wait-for-css: ("dt" + |deprecated_class|, {"display": "block"}, ALL)
// Now we go to a trait with a deprecated method and a deprecated associated const.
go-to: "file://" + |DOC_PATH| + "/lib2/deprecated/trait.NormalTrait.html"
// There should be two deprecated items.
assert-count: ("details" + |deprecated_class|, 2)
// They should be displayed for now.
assert-css: ("details" + |deprecated_class|, {"display": "block"}, ALL)
// We enable the "hide deprecated items" setting.
call-function: ("open-settings-menu", {})
click: "#hide-deprecated-items"
// They shouldn't be displayed anymore.
wait-for-css: ("details" + |deprecated_class|, {"display": "none"}, ALL)
// We disable the setting.
click: "#hide-deprecated-items"
// All of them should be displayed back.
wait-for-css: ("details" + |deprecated_class|, {"display": "block"}, ALL)
// We now go to a struct with a deprecated method which implements a deprecated trait and a trait
// with deprecated associated items.
go-to: "file://" + |DOC_PATH| + "/lib2/deprecated/struct.NonDeprecatedStruct.html"
// There should be five deprecated items (six minus one "future" deprecated)...
assert-count: ("details" + |deprecated_class|, 5)
// One of which being a deprecated impl because the trait itself is deprecated.
assert-count: ("details.implementors-toggle" + |deprecated_class|, 1)
// And another has `since = "TBD"` and should NOT have the `deprecated` class.
assert: "details:not(" + |deprecated_class| + ") #method\.future_deprecated_fn"
// They should all be displayed for now.
assert-css: ("details" + |deprecated_class|, {"display": "block"}, ALL)
// We enable the "hide deprecated items" setting.
call-function: ("open-settings-menu", {})
click: "#hide-deprecated-items"
// They shouldn't be displayed anymore.
wait-for-css: ("details" + |deprecated_class|, {"display": "none"}, ALL)
// We disable the setting.
click: "#hide-deprecated-items"
// All of them should be displayed back.
wait-for-css: ("details" + |deprecated_class|, {"display": "block"}, ALL)
// And now we check with the search results.
call-function: ("perform-search", {"query": "deprecated::depr"})
// There should at least 7 results.
store-count: ("#results ul.search-results.active > a", nb_search_results)
assert: |nb_search_results| >= 7
// There should be at least 5 deprecated items.
store-count: ("#results ul.search-results.active > a" + |deprecated_class|, nb_deprecated_results)
assert: |nb_search_results| >= 5
// Deprecated items should all be displayed.
assert-css: ("#results ul.search-results.active > a" + |deprecated_class|, {"display": "grid"}, ALL)
// We enable the "hide deprecated items" setting.
call-function: ("open-settings-menu", {})
click: "#hide-deprecated-items"
// None of them should be displayed anymore.
wait-for-css: (
"#results ul.search-results.active > a" + |deprecated_class|,
{"display": "none"},
ALL,
)
// Finally we check that the future deprecated item doesn't have the deprecated class in the search
// and therefore isn't impact by the setting.
call-function: ("perform-search", {"query": "deprecated::future_deprecated"})
assert-text: (
"#results ul.search-results.active > a:not(" + |deprecated_class| + ") .path",
" lib2::deprecated::NonDeprecatedStruct::future_deprecated_fn",
)
+43
View File
@@ -368,3 +368,46 @@ fn deref(&self) -> &Self::Target {
&self.0
}
}
pub mod deprecated {
#[deprecated(since = "1.26.0", note = "deprecated")]
pub struct DeprecatedStruct;
pub struct NonDeprecatedStruct;
pub trait NormalTrait {
#[deprecated(since = "1.26.0", note = "deprecated")]
/// doc
const X: usize = 12;
#[deprecated(since = "1.26.0", note = "deprecated")]
/// doc
fn normal_deprecated_fn();
}
#[deprecated(since = "1.26.0", note = "deprecated")]
pub trait DeprecatedTrait {
fn depr_deprecated_fn();
}
impl NonDeprecatedStruct {
#[deprecated(since = "1.26.0", note = "deprecated")]
/// doc
pub fn deprecated_fn() {}
/// doc
pub fn non_deprecated_fn() {}
#[deprecated(since = "TBD", note = "deprecated")]
/// doc
pub fn future_deprecated_fn() {}
}
impl NormalTrait for NonDeprecatedStruct {
fn normal_deprecated_fn() {}
}
impl DeprecatedTrait for NonDeprecatedStruct {
fn depr_deprecated_fn() {}
}
}
+30 -9
View File
@@ -77,19 +77,40 @@ define-function: (
},
)
define-function: (
"open-search",
[],
block {
store-count: (".search-input", __search_input_count)
if: (|__search_input_count| != 0, block {
store-css: ("#alternative-display", {"display": __search_input_display})
})
else: block {
// Block requests with doubled `//`.
// Amazon S3 doesn't support them, but other web hosts do,
// and so do file:/// URLs, which means we need to block
// it here if we want to avoid breaking the main docs site.
// https://github.com/rust-lang/rust/issues/145646
block-network-request: "file://*//*"
store-value: (__search_input_display, "none")
}
if: (|__search_input_display| == "none", block {
// Open search
click: "#search-button"
wait-for: ".search-input"
})
}
)
define-function: (
"perform-search",
[query],
block {
// Block requests with doubled `//`.
// Amazon S3 doesn't support them, but other web hosts do,
// and so do file:/// URLs, which means we need to block
// it here if we want to avoid breaking the main docs site.
// https://github.com/rust-lang/rust/issues/145646
block-network-request: "file://*//*"
// Perform search
click: "#search-button"
wait-for: ".search-input"
call-function: ("open-search", {})
// We empty the search input in case it wasn't empty.
set-property: (".search-input", {"value": ""})
// We write the actual query.
write-into: (".search-input", |query|)
press-key: 'Enter'
// wait for the search to start