diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 6c67916571a40..847e688d03d0a 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -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, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index ddfce7aeb92da..de45922e856f7 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -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, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c86a655c083a5..19974f4847d47 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -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, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 817eda4c52ecc..0e970a042ff0c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2882,6 +2882,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, for_: Type, items: Vec| { let kind = ImplItem(Box::new(Impl { safety: match impl_.of_trait { @@ -2902,6 +2905,7 @@ fn clean_impl<'tcx>( } else { ImplKind::Normal }, + is_deprecated, })); Item::from_def_id_and_parts(def_id.to_def_id(), None, kind, cx) }; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c3bafd3db13ac..93863ea41396a 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -427,6 +427,10 @@ impl Item { }) } + 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 @@ impl Trait { 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, pub(crate) polarity: ty::ImplPolarity, pub(crate) kind: ImplKind, + pub(crate) is_deprecated: bool, } impl Impl { diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 56f10b03d62de..64e361d566c32 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -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); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 63de870f07f45..46a60846f141a 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -141,7 +141,7 @@ pub(crate) struct IndexItem { pub(crate) impl_id: Option, pub(crate) search_type: Option, pub(crate) aliases: Box<[Symbol]>, - pub(crate) deprecation: Option, + pub(crate) is_deprecated: bool, } /// A type used for the search index. @@ -1794,12 +1794,14 @@ fn render_impl( 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() { @@ -1839,10 +1841,20 @@ fn render_impl( 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, "
")?; + write!( + w, + "
" + )?; + deprecation_class = ""; } match &item.kind { clean::MethodItem(..) | clean::RequiredMethodItem(_) => { @@ -1859,7 +1871,7 @@ fn render_impl( .map(|item| format!("{}.{name}", item.type_())); write!( w, - "
\ + "
\ {}", render_rightside(cx, item, render_mode) )?; @@ -1885,7 +1897,7 @@ fn render_impl( let id = cx.derive_id(&source_id); write!( w, - "
\ + "
\ {}", render_rightside(cx, item, render_mode) )?; @@ -1912,7 +1924,7 @@ fn render_impl( let id = cx.derive_id(&source_id); write!( w, - "
\ + "
\ {}", render_rightside(cx, item, render_mode), )?; @@ -1944,7 +1956,7 @@ fn render_impl( let id = cx.derive_id(&source_id); write!( w, - "
\ + "
\ {}", render_rightside(cx, item, render_mode), )?; @@ -1971,7 +1983,7 @@ fn render_impl( let id = cx.derive_id(&source_id); write!( w, - "
\ + "
\ {}", render_rightside(cx, item, render_mode), )?; @@ -2143,11 +2155,18 @@ fn render_impl( } 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("
"); write!( w, - "
\ + "
\ ", if rendering_params.toggle_open_by_default { " open" } else { "" } )?; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 84e93a479b5b5..55e36c462f967 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -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 item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i write!(w, "")? } 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 item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i }; write!( w, - "\ - " + "", + deprecation_attr = deprecation_class_attr(deprecation) )?; render_attributes_in_code(w, myitem, "", cx)?; write!( @@ -396,9 +407,7 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i )?; } _ => { - 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 item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i .into_string(); let (docs_before, docs_after) = if docs.is_empty() { ("", "") } else { ("
", "
") }; + let deprecation_attr = deprecation_class_attr(myitem.is_deprecated(tcx)); write!( w, - "
\ + "\ \ {name}\ \ @@ -442,12 +452,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i {stab_tags}\
\ {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 item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt: 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, "
")?; + write!( + w, + "
" + )?; + deprecation_class = ""; } write!( w, - "
\ + "
\ {}\

{}

", render_rightside(cx, m, RenderMode::Normal), diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 12b207dda5693..30b534003da17 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -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 diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b770a0e2a0e41..ad7ef9b453cec 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -64,7 +64,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\ '); } -: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 diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index b2880a2f4c2b9..9961c1447ec2a 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -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"); diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 347d3d0750ece..0bbeb6931e443 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -43,41 +43,17 @@ } } break; + case "sans-serif-fonts": 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 "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. diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 40ab8be03c93d..1ec7cb4ced06e 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -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") { diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 892cc483dbd6f..2edf7891be400 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -711,7 +711,8 @@ impl FromClean for PolyTrait { impl FromClean 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), diff --git a/tests/rustdoc-gui/setting-hide-deprecated.goml b/tests/rustdoc-gui/setting-hide-deprecated.goml new file mode 100644 index 0000000000000..6dc5a6bff175d --- /dev/null +++ b/tests/rustdoc-gui/setting-hide-deprecated.goml @@ -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", +) diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs index b87fdeea89da0..1367b17b37b2f 100644 --- a/tests/rustdoc-gui/src/lib2/lib.rs +++ b/tests/rustdoc-gui/src/lib2/lib.rs @@ -368,3 +368,46 @@ impl std::ops::Deref for Derefer { &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() {} + } +} diff --git a/tests/rustdoc-gui/utils.goml b/tests/rustdoc-gui/utils.goml index c0625ead2f1aa..3d9bdd1ac1498 100644 --- a/tests/rustdoc-gui/utils.goml +++ b/tests/rustdoc-gui/utils.goml @@ -59,19 +59,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