diff --git a/Cargo.lock b/Cargo.lock index 281599a21fc14..1a7d7e3f5d7d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4826,6 +4826,7 @@ dependencies = [ "tracing", "tracing-subscriber", "tracing-tree", + "unicode-segmentation", ] [[package]] diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index fe531f0ff5985..dfd7414652fa7 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -23,6 +23,7 @@ tempfile = "3" tracing = "0.1" tracing-tree = "0.3.0" threadpool = "1.8.1" +unicode-segmentation = "1.9" [dependencies.tracing-subscriber] version = "0.3.3" diff --git a/src/librustdoc/html/escape.rs b/src/librustdoc/html/escape.rs index ea4b573aeb955..691f86847b56d 100644 --- a/src/librustdoc/html/escape.rs +++ b/src/librustdoc/html/escape.rs @@ -5,6 +5,8 @@ use std::fmt; +use unicode_segmentation::UnicodeSegmentation; + /// Wrapper struct which will emit the HTML-escaped version of the contained /// string when passed to a format string. pub(crate) struct Escape<'a>(pub &'a str); @@ -74,3 +76,56 @@ impl<'a> fmt::Display for EscapeBodyText<'a> { Ok(()) } } + +/// Wrapper struct which will emit the HTML-escaped version of the contained +/// string when passed to a format string. This function also word-breaks +/// CamelCase and snake_case word names. +/// +/// This is only safe to use for text nodes. If you need your output to be +/// safely contained in an attribute, use [`Escape`]. If you don't know the +/// difference, use [`Escape`]. +pub(crate) struct EscapeBodyTextWithWbr<'a>(pub &'a str); + +impl<'a> fmt::Display for EscapeBodyTextWithWbr<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let EscapeBodyTextWithWbr(text) = *self; + if text.len() < 8 { + return EscapeBodyText(text).fmt(fmt); + } + let mut last = 0; + let mut it = text.grapheme_indices(true).peekable(); + let _ = it.next(); // don't insert wbr before first char + while let Some((i, s)) = it.next() { + let pk = it.peek(); + if s.chars().all(|c| c.is_whitespace()) { + // don't need "First Second"; the space is enough + EscapeBodyText(&text[last..i]).fmt(fmt)?; + last = i; + continue; + } + let is_uppercase = || s.chars().any(|c| c.is_uppercase()); + let next_is_uppercase = + || pk.map_or(true, |(_, t)| t.chars().any(|c| c.is_uppercase())); + let next_is_underscore = || pk.map_or(true, |(_, t)| t.contains('_')); + let next_is_colon = || pk.map_or(true, |(_, t)| t.contains(':')); + if i - last > 3 && is_uppercase() && !next_is_uppercase() { + EscapeBodyText(&text[last..i]).fmt(fmt)?; + fmt.write_str("")?; + last = i; + } else if (s.contains(':') && !next_is_colon()) + || (s.contains('_') && !next_is_underscore()) + { + EscapeBodyText(&text[last..i + 1]).fmt(fmt)?; + fmt.write_str("")?; + last = i + 1; + } + } + if last < text.len() { + EscapeBodyText(&text[last..]).fmt(fmt)?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests; diff --git a/src/librustdoc/html/escape/tests.rs b/src/librustdoc/html/escape/tests.rs new file mode 100644 index 0000000000000..a09649e9e18dc --- /dev/null +++ b/src/librustdoc/html/escape/tests.rs @@ -0,0 +1,68 @@ +// basic examples +#[test] +fn escape_body_text_with_wbr() { + use super::EscapeBodyTextWithWbr as E; + // extreme corner cases + assert_eq!(&E("").to_string(), ""); + assert_eq!(&E("a").to_string(), "a"); + assert_eq!(&E("A").to_string(), "A"); + assert_eq!(&E("_").to_string(), "_"); + assert_eq!(&E(":").to_string(), ":"); + assert_eq!(&E(" ").to_string(), " "); + assert_eq!(&E("___________").to_string(), "___________"); + assert_eq!(&E(":::::::::::").to_string(), ":::::::::::"); + assert_eq!(&E(" ").to_string(), " "); + // real(istic) examples + assert_eq!(&E("FirstSecond").to_string(), "FirstSecond"); + assert_eq!(&E("First_Second").to_string(), "First_Second"); + assert_eq!(&E("First Second").to_string(), "First Second"); + assert_eq!(&E("First HSecond").to_string(), "First HSecond"); + assert_eq!(&E("First HTTPSecond").to_string(), "First HTTPSecond"); + assert_eq!(&E("First SecondThird").to_string(), "First SecondThird"); + assert_eq!(&E("First_Second").to_string(), "First<T>_Second"); + assert_eq!(&E("first_second").to_string(), "first_second"); + assert_eq!(&E("first:second").to_string(), "first:second"); + assert_eq!(&E("first::second").to_string(), "first::second"); + assert_eq!(&E("MY_CONSTANT").to_string(), "MY_CONSTANT"); + // a string won't get wrapped if it's less than 8 bytes + assert_eq!(&E("HashSet").to_string(), "HashSet"); + // an individual word won't get wrapped if it's less than 4 bytes + assert_eq!(&E("VecDequeue").to_string(), "VecDequeue"); + assert_eq!(&E("VecDequeueSet").to_string(), "VecDequeueSet"); + // how to handle acronyms + assert_eq!(&E("BTreeMap").to_string(), "BTreeMap"); + assert_eq!(&E("HTTPSProxy").to_string(), "HTTPSProxy"); + // more corners + assert_eq!(&E("ṼẽçÑñéå").to_string(), "ṼẽçÑñéå"); + assert_eq!(&E("V\u{0300}e\u{0300}c\u{0300}D\u{0300}e\u{0300}q\u{0300}u\u{0300}e\u{0300}u\u{0300}e\u{0300}").to_string(), "V\u{0300}e\u{0300}c\u{0300}D\u{0300}e\u{0300}q\u{0300}u\u{0300}e\u{0300}u\u{0300}e\u{0300}"); + assert_eq!(&E("LPFNACCESSIBLEOBJECTFROMWINDOW").to_string(), "LPFNACCESSIBLEOBJECTFROMWINDOW"); +} +// property test +#[test] +fn escape_body_text_with_wbr_makes_sense() { + use itertools::Itertools as _; + + use super::EscapeBodyTextWithWbr as E; + const C: [u8; 3] = [b'a', b'A', b'_']; + for chars in [ + C.into_iter(), + C.into_iter(), + C.into_iter(), + C.into_iter(), + C.into_iter(), + C.into_iter(), + C.into_iter(), + C.into_iter(), + ] + .into_iter() + .multi_cartesian_product() + { + let s = String::from_utf8(chars).unwrap(); + assert_eq!(s.len(), 8); + let esc = E(&s).to_string(); + assert!(!esc.contains("")); + assert!(!esc.ends_with("")); + assert!(!esc.starts_with("")); + assert_eq!(&esc.replace("", ""), &s); + } +} diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index d6aed75103dc4..bb5ac303ffd63 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -32,7 +32,7 @@ use crate::clean::utils::find_nearest_parent_module; use crate::clean::{self, ExternalCrate, PrimitiveType}; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; -use crate::html::escape::Escape; +use crate::html::escape::{Escape, EscapeBodyText}; use crate::html::render::Context; use crate::passes::collect_intra_doc_links::UrlFragment; @@ -988,6 +988,7 @@ pub(crate) fn anchor<'a, 'cx: 'a>( f, r#"{text}"#, path = join_with_double_colon(&fqp), + text = EscapeBodyText(text.as_str()), ) } else { f.write_str(text.as_str()) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 7dfcc88398faf..780cda9b1cdf4 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -69,6 +69,8 @@ struct PageLayout<'a> { display_krate_version_extra: &'a str, } +pub(crate) use crate::html::render::sidebar::filters; + pub(crate) fn render( layout: &Layout, page: &Page<'_>, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index aaac8678264aa..b5cc495ce41ef 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -30,7 +30,7 @@ mod tests; mod context; mod print_item; -mod sidebar; +pub(crate) mod sidebar; mod span_map; mod type_layout; mod write_shared; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 24476e80778e1..eec6df9dd2013 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -29,7 +29,7 @@ use crate::clean; use crate::config::ModuleSorting; use crate::formats::item_type::ItemType; use crate::formats::Impl; -use crate::html::escape::Escape; +use crate::html::escape::{Escape, EscapeBodyTextWithWbr}; use crate::html::format::{ display_fn, join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause, visibility_print_with_space, Buffer, Ending, PrintWithSpace, @@ -423,7 +423,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: "
{}extern crate {} as {};", visibility_print_with_space(myitem, cx), anchor(myitem.item_id.expect_def_id(), src, cx), - myitem.name.unwrap(), + EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()), ), None => write!( w, @@ -520,7 +520,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: {stab_tags}\
\ {docs_before}{docs}{docs_after}", - name = myitem.name.unwrap(), + name = EscapeBodyTextWithWbr(myitem.name.unwrap().as_str()), visibility_and_hidden = visibility_and_hidden, stab_tags = extra_info_tags(myitem, item, tcx), class = myitem.type_(), @@ -558,7 +558,7 @@ fn extra_info_tags<'a, 'tcx: 'a>( display_fn(move |f| { write!( f, - r#"{contents}"#, + r#"{contents}"#, title = Escape(title), ) }) diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6e826446c0e0e..101cc839f0988 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -77,6 +77,22 @@ impl<'a> Link<'a> { } } +pub(crate) mod filters { + use std::fmt::Display; + + use rinja::filters::Safe; + + use crate::html::escape::EscapeBodyTextWithWbr; + use crate::html::render::display_fn; + pub(crate) fn wrapped(v: T) -> rinja::Result> + where + T: Display, + { + let string = v.to_string(); + Ok(Safe(display_fn(move |f| EscapeBodyTextWithWbr(&string).fmt(f)))) + } +} + pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let blocks: Vec> = match *it.kind { clean::StructItem(ref s) => sidebar_struct(cx, it, s), diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index e936e1ca07ecd..cafe5fe4c8779 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -586,12 +586,15 @@ ul.block, .block li { } .sidebar h2 { + text-wrap: balance; overflow-wrap: anywhere; padding: 0; margin: 0.7rem 0; } .sidebar h3 { + text-wrap: balance; + overflow-wrap: anywhere; font-size: 1.125rem; /* 18px */ padding: 0; margin: 0; @@ -2222,7 +2225,7 @@ in src-script.js and main.js width: 33%; } .item-table > li > div { - word-break: break-all; + overflow-wrap: anywhere; } } diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index cdf01fa7a97e8..65c4304e20207 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -98,7 +98,7 @@ {# #} {% endif %}

{# #} - {{display_krate}} {# #} + {{display_krate|wrapped|safe}} {# #} {% if !display_krate_version_number.is_empty() %} {{+ display_krate_version_number}} {% endif %} diff --git a/src/librustdoc/html/templates/sidebar.html b/src/librustdoc/html/templates/sidebar.html index 3251b4c14c95a..0990c2716b8f2 100644 --- a/src/librustdoc/html/templates/sidebar.html +++ b/src/librustdoc/html/templates/sidebar.html @@ -1,6 +1,6 @@ {% if !title.is_empty() %}

{# #} - {{title_prefix}}{{title}} {# #} + {{title_prefix}}{{title|wrapped|safe}} {# #}

{% endif %} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6e8fdd624434..1f15605d8beed 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2731,6 +2731,7 @@ impl<'test> TestCx<'test> { #[rustfmt::skip] let tidy_args = [ + "--new-blocklevel-tags", "rustdoc-search", "--indent", "yes", "--indent-spaces", "2", "--wrap", "0", diff --git a/tests/rustdoc-gui/duplicate-macro-reexport.goml b/tests/rustdoc-gui/duplicate-macro-reexport.goml index 7d01c88f31ba5..a838d99c4bffc 100644 --- a/tests/rustdoc-gui/duplicate-macro-reexport.goml +++ b/tests/rustdoc-gui/duplicate-macro-reexport.goml @@ -4,11 +4,11 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/macro.a.html" wait-for: ".sidebar-elems .macro" // Check there is only one macro named "a" listed in the sidebar. assert-count: ( - "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='a']", + "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[normalize-space()='a']", 1, ) // Check there is only one macro named "b" listed in the sidebar. assert-count: ( - "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[text()='b']", + "//*[@class='sidebar-elems']//*[@class='block macro']//li/a[normalize-space()='b']", 1, ) diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml index 602b8d6f5b34c..26e9bf515a3ff 100644 --- a/tests/rustdoc-gui/font-weight.goml +++ b/tests/rustdoc-gui/font-weight.goml @@ -1,8 +1,8 @@ // This test checks that the font weight is correctly applied. go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html" -assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"}) +assert-css: ("//*[@class='rust item-decl']//a[normalize-space()='Alias']", {"font-weight": "400"}) assert-css: ( - "//*[@class='structfield section-header']//a[text()='Alias']", + "//*[@class='structfield section-header']//a[normalize-space()='Alias']", {"font-weight": "400"}, ) assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"}) diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index 1eb46e832b70b..7a0194c6cc1f6 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -12,11 +12,11 @@ assert-position: (".item-info .stab", {"x": 245}) // test for . set-window-size: (850, 800) store-position: ( - "//*[@class='stab portability']//code[text()='Win32_System']", + "//*[@class='stab portability']//code[normalize-space()='Win32_System']", {"x": first_line_x, "y": first_line_y}, ) store-position: ( - "//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']", + "//*[@class='stab portability']//code[normalize-space()='Win32_System_Diagnostics']", {"x": second_line_x, "y": second_line_y}, ) assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml index 0582bd2cad36e..a8363f29dd5de 100644 --- a/tests/rustdoc-gui/label-next-to-symbol.goml +++ b/tests/rustdoc-gui/label-next-to-symbol.goml @@ -23,11 +23,12 @@ assert-css: ( // table like view assert-css: (".desc.docblock-short", { "padding-left": "0px" }) compare-elements-position-near: ( - "//*[@class='item-name']//a[text()='replaced_function']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']", ".item-name .stab.deprecated", {"y": 2}, ) -compare-elements-position: ( +// "Unix" part is on second line +compare-elements-position-false: ( ".item-name .stab.deprecated", ".item-name .stab.portability", ["y"], @@ -35,8 +36,8 @@ compare-elements-position: ( // Ensure no wrap compare-elements-position: ( - "//*[@class='item-name']//a[text()='replaced_function']/..", - "//*[@class='desc docblock-short'][text()='a thing with a label']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']/..", + "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']", ["y"], ) @@ -45,7 +46,7 @@ set-window-size: (600, 600) // staggered layout with 2em spacing assert-css: (".desc.docblock-short", { "padding-left": "32px" }) compare-elements-position-near: ( - "//*[@class='item-name']//a[text()='replaced_function']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']", ".item-name .stab.deprecated", {"y": 2}, ) @@ -57,13 +58,13 @@ compare-elements-position: ( // Ensure wrap compare-elements-position-false: ( - "//*[@class='item-name']//a[text()='replaced_function']/..", - "//*[@class='desc docblock-short'][text()='a thing with a label']", + "//*[@class='item-name']//a[normalize-space()='replaced_function']/..", + "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']", ["y"], ) compare-elements-position-false: ( ".item-name .stab.deprecated", - "//*[@class='desc docblock-short'][text()='a thing with a label']", + "//*[@class='desc docblock-short'][normalize-space()='a thing with a label']", ["y"], ) @@ -73,7 +74,7 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/cfgs/index.html" // This part of the tags should not be on the same line as the beginning since the width // is too small for that. compare-elements-position-false: ( - "//*[@class='stab portability']/code[text()='appservice-api-c']", - "//*[@class='stab portability']/code[text()='server']", + "//*[@class='stab portability']/code[normalize-space()='appservice-api-c']", + "//*[@class='stab portability']/code[normalize-space()='server']", ["y"], ) diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml index 6ee810c5768c2..e2a8a43007eb0 100644 --- a/tests/rustdoc-gui/notable-trait.goml +++ b/tests/rustdoc-gui/notable-trait.goml @@ -9,19 +9,19 @@ define-function: ( block { // Checking they have the same y position. compare-elements-position: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", ["y"], ) // Checking they don't have the same x position. compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", ["x"], ) // The `i` should be *after* the type. assert-position: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", {"x": |x|}, ) assert-position: ( @@ -70,7 +70,7 @@ call-function: ("check-notable-tooltip-position-complete", { // Now only the `i` should be on the next line. set-window-size: (1055, 600) compare-elements-position-false: ( - "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']", + "//*[@id='method.create_an_iterator_from_read']//a[normalize-space()='NotableStructWithLongName']", "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']", ["y", "x"], ) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 9825f92b45351..e8da43eb896bc 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -20,11 +20,11 @@ define-function: ( ALL, ) assert-css: ( - "//*[@class='desc'][text()='Just a normal struct.']", + "//*[@class='desc'][normalize-space()='Just a normal struct.']", {"color": |desc_color|}, ) assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']", + "//*[@class='result-name']//*[normalize-space()='test_docs::']", {"color": |path_color|}, ) @@ -85,19 +85,19 @@ define-function: ( move-cursor-to: ".search-input" focus: ".search-input" // To ensure the `` container isn't focused or hovered. assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a", + "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a", {"color": |path_color|, "background-color": "transparent"}, ALL, ) // Checking color and background on hover. - move-cursor-to: "//*[@class='desc'][text()='Just a normal struct.']" + move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal struct.']" assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']", + "//*[@class='result-name']//*[normalize-space()='test_docs::']", {"color": |hover_path_color|}, ) assert-css: ( - "//*[@class='result-name']//*[text()='test_docs::']/ancestor::a", + "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a", {"color": |hover_path_color|, "background-color": |hover_background|}, ) } diff --git a/tests/rustdoc-gui/sidebar-macro-reexport.goml b/tests/rustdoc-gui/sidebar-macro-reexport.goml index 0f7ef6c355828..cad25507fbbd6 100644 --- a/tests/rustdoc-gui/sidebar-macro-reexport.goml +++ b/tests/rustdoc-gui/sidebar-macro-reexport.goml @@ -2,4 +2,4 @@ // displayed twice in the sidebar. go-to: "file://" + |DOC_PATH| + "/test_docs/macro.repro.html" wait-for: ".sidebar-elems .block.macro a" -assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1) +assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[normalize-space()='repro']", 1) diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml index b4ff483c18097..4ada4837a5774 100644 --- a/tests/rustdoc-gui/sidebar-mobile.goml +++ b/tests/rustdoc-gui/sidebar-mobile.goml @@ -25,9 +25,12 @@ click: ".sidebar-menu-toggle" assert-css: (".sidebar", {"left": "0px"}) // Make sure the "struct Foo" header is hidden, since the mobile topbar already does it. -assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='Foo']/parent::h2", {"display": "none"}) +assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[normalize-space()='Foo']/parent::h2", {"display": "none"}) // Make sure the global navigation is still here. -assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In crate test_docs']/parent::h2", {"display": "block"}) +assert-css: ( + "//nav[contains(@class, 'sidebar')]//h2/a[normalize-space()='In crate test_docs']/parent::h2", + {"display": "block"} +) // Click elsewhere. click: "body" diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml index ef0b5ab38b138..6afccf6a95fe2 100644 --- a/tests/rustdoc-gui/sidebar-source-code.goml +++ b/tests/rustdoc-gui/sidebar-source-code.goml @@ -66,12 +66,12 @@ click: "#sidebar-button" // We wait for the sidebar to be expanded. wait-for-css: (".src-sidebar-expanded nav.sidebar", {"width": "300px"}) assert: "//*[@class='dir-entry' and @open]/*[text()='lib2']" -assert: "//*[@class='dir-entry' and @open]/*[text()='another_folder']" -assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']" +assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='another_folder']" +assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='sub_mod']" // Only "another_folder" should be "open" in "lib2". -assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']" +assert: "//*[@class='dir-entry' and not(@open)]/*[normalize-space()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='src-sidebar']/details[not(text()='lib2') and not(@open)]", 11) +assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 11) // We now switch to mobile mode. set-window-size: (600, 600) diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml index 940851ea14632..3508b26a0bf24 100644 --- a/tests/rustdoc-gui/source-anchor-scroll.goml +++ b/tests/rustdoc-gui/source-anchor-scroll.goml @@ -11,7 +11,7 @@ click: '//a[text() = "barbar" and @href="#5-7"]' assert-property: ("html", {"scrollTop": "123"}) click: '//a[text() = "bar" and @href="#28-36"]' assert-property: ("html", {"scrollTop": "154"}) -click: '//a[text() = "sub_fn" and @href="#2-4"]' +click: '//a[normalize-space() = "sub_fn" and @href="#2-4"]' assert-property: ("html", {"scrollTop": "51"}) // We now check that clicking on lines doesn't change the scroll diff --git a/tests/rustdoc/extremely_long_typename.extremely_long_typename.html b/tests/rustdoc/extremely_long_typename.extremely_long_typename.html new file mode 100644 index 0000000000000..b20e59866dac6 --- /dev/null +++ b/tests/rustdoc/extremely_long_typename.extremely_long_typename.html @@ -0,0 +1 @@ +
  • \ No newline at end of file diff --git a/tests/rustdoc/extremely_long_typename.rs b/tests/rustdoc/extremely_long_typename.rs new file mode 100644 index 0000000000000..212afe2d11033 --- /dev/null +++ b/tests/rustdoc/extremely_long_typename.rs @@ -0,0 +1,7 @@ +// ignore-tidy-linelength +// Make sure that, if an extremely long type name is named, +// the item table has it line wrapped. +// There should be some reasonably-placed `` tags in the snapshot file. + +// @snapshot extremely_long_typename "extremely_long_typename/index.html" '//ul[@class="item-table"]/li' +pub struct CreateSubscriptionPaymentSettingsPaymentMethodOptionsCustomerBalanceBankTransferEuBankTransfer; diff --git a/tests/rustdoc/item-desc-list-at-start.item-table.html b/tests/rustdoc/item-desc-list-at-start.item-table.html index 72bde573cead3..cff4f816529c3 100644 --- a/tests/rustdoc/item-desc-list-at-start.item-table.html +++ b/tests/rustdoc/item-desc-list-at-start.item-table.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file