Rollup merge of #129796 - GuillaumeGomez:unify-code-examples, r=notriddle

Unify scraped examples with other code examples

Fixes #129763.

This first PR both fixes #129763 but also unifies buttons display for code examples:

![image](https://github.com/user-attachments/assets/c8475945-dcc3-4c25-8d7d-1659f85301c8)

You can test it [here](https://rustdoc.crud.net/imperio/unify-code-examples/doc/scrape_examples/fn.test.html) and [here](https://rustdoc.crud.net/imperio/unify-code-examples/doc/scrape_examples/fn.test_many.html).

I'm planning to send a follow-up to make the buttons generated in JS directly (or I can do it in this PR directly if you prefer).

cc ```@willcrichton```
r? ```@notriddle```
This commit is contained in:
Matthias Krüger 2024-09-05 18:58:56 +02:00 committed by GitHub
commit 9be97ae8e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 380 additions and 156 deletions

View File

@ -2506,28 +2506,6 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES; let needs_expansion = line_max - line_min > NUM_VISIBLE_LINES;
let locations_encoded = serde_json::to_string(&line_ranges).unwrap(); let locations_encoded = serde_json::to_string(&line_ranges).unwrap();
write!(
&mut w,
"<div class=\"scraped-example {expanded_cls}\" data-locs=\"{locations}\">\
<div class=\"scraped-example-title\">\
{name} (<a href=\"{url}\">{title}</a>)\
</div>\
<div class=\"code-wrapper\">",
expanded_cls = if needs_expansion { "" } else { "expanded" },
name = call_data.display_name,
url = init_url,
title = init_title,
// The locations are encoded as a data attribute, so they can be read
// later by the JS for interactions.
locations = Escape(&locations_encoded)
)
.unwrap();
if line_ranges.len() > 1 {
w.write_str(r#"<button class="prev">&pr;</button> <button class="next">&sc;</button>"#)
.unwrap();
}
// Look for the example file in the source map if it exists, otherwise return a dummy span // Look for the example file in the source map if it exists, otherwise return a dummy span
let file_span = (|| { let file_span = (|| {
let source_map = tcx.sess.source_map(); let source_map = tcx.sess.source_map();
@ -2558,9 +2536,16 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
cx, cx,
&cx.root_path(), &cx.root_path(),
highlight::DecorationInfo(decoration_info), highlight::DecorationInfo(decoration_info),
sources::SourceContext::Embedded { offset: line_min, needs_expansion }, sources::SourceContext::Embedded(sources::ScrapedInfo {
needs_prev_next_buttons: line_ranges.len() > 1,
needs_expansion,
offset: line_min,
name: &call_data.display_name,
url: init_url,
title: init_title,
locations: locations_encoded,
}),
); );
w.write_str("</div></div>").unwrap();
true true
}; };

View File

@ -290,9 +290,34 @@ pub(crate) fn clean_path<F, P>(src_root: &Path, p: &Path, mut f: F, mut parent:
} }
} }
pub(crate) enum SourceContext { pub(crate) struct ScrapedInfo<'a> {
pub(crate) offset: usize,
pub(crate) needs_prev_next_buttons: bool,
pub(crate) name: &'a str,
pub(crate) url: &'a str,
pub(crate) title: &'a str,
pub(crate) locations: String,
pub(crate) needs_expansion: bool,
}
#[derive(Template)]
#[template(path = "scraped_source.html")]
struct ScrapedSource<'a, Code: std::fmt::Display> {
info: ScrapedInfo<'a>,
lines: RangeInclusive<usize>,
code_html: Code,
}
#[derive(Template)]
#[template(path = "source.html")]
struct Source<Code: std::fmt::Display> {
lines: RangeInclusive<usize>,
code_html: Code,
}
pub(crate) enum SourceContext<'a> {
Standalone, Standalone,
Embedded { offset: usize, needs_expansion: bool }, Embedded(ScrapedInfo<'a>),
} }
/// Wrapper struct to render the source code of a file. This will do things like /// Wrapper struct to render the source code of a file. This will do things like
@ -304,23 +329,8 @@ pub(crate) fn print_src(
context: &Context<'_>, context: &Context<'_>,
root_path: &str, root_path: &str,
decoration_info: highlight::DecorationInfo, decoration_info: highlight::DecorationInfo,
source_context: SourceContext, source_context: SourceContext<'_>,
) { ) {
#[derive(Template)]
#[template(path = "source.html")]
struct Source<Code: std::fmt::Display> {
embedded: bool,
needs_expansion: bool,
lines: RangeInclusive<usize>,
code_html: Code,
}
let lines = s.lines().count();
let (embedded, needs_expansion, lines) = match source_context {
SourceContext::Standalone => (false, false, 1..=lines),
SourceContext::Embedded { offset, needs_expansion } => {
(true, needs_expansion, (1 + offset)..=(lines + offset))
}
};
let current_href = context let current_href = context
.href_from_span(clean::Span::new(file_span), false) .href_from_span(clean::Span::new(file_span), false)
.expect("only local crates should have sources emitted"); .expect("only local crates should have sources emitted");
@ -333,5 +343,14 @@ struct Source<Code: std::fmt::Display> {
); );
Ok(()) Ok(())
}); });
Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap(); let lines = s.lines().count();
match source_context {
SourceContext::Standalone => {
Source { lines: (1..=lines), code_html: code }.render_into(&mut writer).unwrap()
}
SourceContext::Embedded(info) => {
let lines = (1 + info.offset)..=(lines + info.offset);
ScrapedSource { info, lines, code_html: code }.render_into(&mut writer).unwrap();
}
};
} }

View File

@ -59,6 +59,8 @@ nav.sub {
--copy-path-button-color: #999; --copy-path-button-color: #999;
--copy-path-img-filter: invert(50%); --copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(35%); --copy-path-img-hover-filter: invert(35%);
--code-example-button-color: #7f7f7f;
--code-example-button-hover-color: #595959;
--codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-hover-color: rgb(255, 142, 0);
@ -162,6 +164,8 @@ nav.sub {
--copy-path-button-color: #999; --copy-path-button-color: #999;
--copy-path-img-filter: invert(50%); --copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(65%); --copy-path-img-hover-filter: invert(65%);
--code-example-button-color: #7f7f7f;
--code-example-button-hover-color: #a5a5a5;
--codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-hover-color: rgb(255, 142, 0);

View File

@ -378,7 +378,7 @@ pre.item-decl {
.src .content pre { .src .content pre {
padding: 20px; padding: 20px;
} }
.rustdoc.src .example-wrap pre.src-line-numbers { .rustdoc.src .example-wrap .src-line-numbers {
padding: 20px 0 20px 4px; padding: 20px 0 20px 4px;
} }
@ -757,10 +757,32 @@ ul.block, .block li, .block ul {
margin-bottom: 10px; margin-bottom: 10px;
} }
.rustdoc .example-wrap > pre { .rustdoc .example-wrap > pre,
.rustdoc .scraped-example .src-line-numbers,
.rustdoc .scraped-example .src-line-numbers > pre {
border-radius: 6px; border-radius: 6px;
} }
/*
If the code example line numbers are displayed, there will be a weird radius in the middle from
both the code example and the line numbers, so we need to remove the radius in this case.
*/
.rustdoc .example-wrap > .example-line-numbers,
.rustdoc .scraped-example .src-line-numbers,
.rustdoc .scraped-example .src-line-numbers > pre {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.rustdoc .example-wrap > .example-line-numbers + pre,
.rustdoc .scraped-example .rust {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.rustdoc .scraped-example {
position: relative;
}
/* For the last child of a div, the margin will be taken care of /* For the last child of a div, the margin will be taken care of
by the margin-top of the next item. */ by the margin-top of the next item. */
.rustdoc .example-wrap:last-child { .rustdoc .example-wrap:last-child {
@ -772,15 +794,36 @@ ul.block, .block li, .block ul {
flex-grow: 1; flex-grow: 1;
} }
.rustdoc:not(.src) .example-wrap pre { .scraped-example:not(.expanded) .example-wrap {
/* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
* of lines shown in the un-expanded example code viewer. This pre needs to have
* a max-height equal to line-height * N. The line-height is currently 1.5em,
* and we include additional 10px for padding. */
max-height: calc(1.5em * 5 + 10px);
}
.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers,
.rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers > pre,
.rustdoc:not(.src) .scraped-example:not(.expanded) pre.rust {
padding-bottom: 0;
/* See above comment, should be the same max-height. */
overflow: auto hidden; overflow: auto hidden;
} }
.rustdoc:not(.src) .scraped-example .src-line-numbers {
padding-top: 0;
}
.rustdoc:not(.src) .scraped-example.expanded .src-line-numbers {
padding-bottom: 0;
}
.rustdoc:not(.src) .example-wrap pre {
overflow: auto;
}
.rustdoc .example-wrap pre.example-line-numbers, .rustdoc .example-wrap pre.example-line-numbers,
.rustdoc .example-wrap pre.src-line-numbers { .rustdoc .example-wrap .src-line-numbers {
flex-grow: 0;
min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */ min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
overflow: initial; flex-grow: 0;
text-align: right; text-align: right;
-webkit-user-select: none; -webkit-user-select: none;
user-select: none; user-select: none;
@ -788,7 +831,7 @@ ul.block, .block li, .block ul {
color: var(--src-line-numbers-span-color); color: var(--src-line-numbers-span-color);
} }
.rustdoc .example-wrap pre.src-line-numbers { .rustdoc .scraped-example .src-line-numbers {
padding: 14px 0; padding: 14px 0;
} }
.src-line-numbers a, .src-line-numbers span { .src-line-numbers a, .src-line-numbers span {
@ -1500,17 +1543,23 @@ instead, we check that it's not a "finger" cursor.
.example-wrap .button-holder.keep-visible { .example-wrap .button-holder.keep-visible {
visibility: visible; visibility: visible;
} }
.example-wrap .button-holder .copy-button, .example-wrap .test-arrow { .example-wrap .button-holder > * {
background: var(--main-background-color); background: var(--main-background-color);
cursor: pointer; cursor: pointer;
border-radius: var(--button-border-radius); border-radius: var(--button-border-radius);
height: var(--copy-path-height); height: var(--copy-path-height);
width: var(--copy-path-width); width: var(--copy-path-width);
border: 0;
color: var(--code-example-button-color);
}
.example-wrap .button-holder > *:hover {
color: var(--code-example-button-hover-color);
}
.example-wrap .button-holder > *:not(:first-child) {
margin-left: var(--button-left-margin);
} }
.example-wrap .button-holder .copy-button { .example-wrap .button-holder .copy-button {
margin-left: var(--button-left-margin);
padding: 2px 0 0 4px; padding: 2px 0 0 4px;
border: 0;
} }
.example-wrap .button-holder .copy-button::before, .example-wrap .button-holder .copy-button::before,
.example-wrap .test-arrow::before { .example-wrap .test-arrow::before {
@ -2254,6 +2303,7 @@ in src-script.js and main.js
} }
} }
/* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */ /* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */
@media (min-width: 701px) { @media (min-width: 701px) {
/* Places file-link for a scraped example on top of the example to save space. /* Places file-link for a scraped example on top of the example to save space.
@ -2356,99 +2406,41 @@ in src-script.js and main.js
color: var(--scrape-example-help-hover-color); color: var(--scrape-example-help-hover-color);
} }
.scraped-example { .scraped-example:not(.expanded) .example-wrap::before,
/* So .scraped-example-title can be positioned absolutely */ .scraped-example:not(.expanded) .example-wrap::after {
position: relative;
}
.scraped-example .code-wrapper {
position: relative;
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
.scraped-example:not(.expanded) .code-wrapper {
/* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
* of lines shown in the un-expanded example code viewer. This pre needs to have
* a max-height equal to line-height * N. The line-height is currently 1.5em,
* and we include additional 10px for padding. */
max-height: calc(1.5em * 5 + 10px);
}
.scraped-example:not(.expanded) .code-wrapper pre {
overflow-y: hidden;
padding-bottom: 0;
/* See above comment, should be the same max-height. */
max-height: calc(1.5em * 5 + 10px);
}
.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,
.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre {
/* See above comment, except this height is based on HIDDEN_MAX_LINES. */
max-height: calc(1.5em * 10 + 10px);
}
.scraped-example .code-wrapper .next,
.scraped-example .code-wrapper .prev,
.scraped-example .code-wrapper .expand {
color: var(--main-color);
position: absolute;
top: 0.25em;
z-index: 1;
padding: 0;
background: none;
border: none;
/* iOS button gradient: https://stackoverflow.com/q/5438567 */
-webkit-appearance: none;
opacity: 1;
}
.scraped-example .code-wrapper .prev {
right: 2.25em;
}
.scraped-example .code-wrapper .next {
right: 1.25em;
}
.scraped-example .code-wrapper .expand {
right: 0.25em;
}
.scraped-example:not(.expanded) .code-wrapper::before,
.scraped-example:not(.expanded) .code-wrapper::after {
content: " "; content: " ";
width: 100%; width: 100%;
height: 5px; height: 5px;
position: absolute; position: absolute;
z-index: 1; z-index: 1;
} }
.scraped-example:not(.expanded) .code-wrapper::before { .scraped-example:not(.expanded) .example-wrap::before {
top: 0; top: 0;
background: linear-gradient(to bottom, background: linear-gradient(to bottom,
var(--scrape-example-code-wrapper-background-start), var(--scrape-example-code-wrapper-background-start),
var(--scrape-example-code-wrapper-background-end)); var(--scrape-example-code-wrapper-background-end));
} }
.scraped-example:not(.expanded) .code-wrapper::after { .scraped-example:not(.expanded) .example-wrap::after {
bottom: 0; bottom: 0;
background: linear-gradient(to top, background: linear-gradient(to top,
var(--scrape-example-code-wrapper-background-start), var(--scrape-example-code-wrapper-background-start),
var(--scrape-example-code-wrapper-background-end)); var(--scrape-example-code-wrapper-background-end));
} }
.scraped-example .code-wrapper .example-wrap { .scraped-example:not(.expanded) {
width: 100%; width: 100%;
overflow-y: hidden; overflow-y: hidden;
margin-bottom: 0; margin-bottom: 0;
} }
.scraped-example:not(.expanded) .code-wrapper .example-wrap { .scraped-example:not(.expanded) {
overflow-x: hidden; overflow-x: hidden;
} }
.scraped-example .example-wrap .rust span.highlight { .scraped-example .rust span.highlight {
background: var(--scrape-example-code-line-highlight); background: var(--scrape-example-code-line-highlight);
} }
.scraped-example .example-wrap .rust span.highlight.focus { .scraped-example .rust span.highlight.focus {
background: var(--scrape-example-code-line-highlight-focus); background: var(--scrape-example-code-line-highlight-focus);
} }
@ -2542,6 +2534,8 @@ by default.
--copy-path-button-color: #999; --copy-path-button-color: #999;
--copy-path-img-filter: invert(50%); --copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(35%); --copy-path-img-hover-filter: invert(35%);
--code-example-button-color: #7f7f7f;
--code-example-button-hover-color: #595959;
--codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-hover-color: rgb(255, 142, 0);
@ -2644,6 +2638,8 @@ by default.
--copy-path-button-color: #999; --copy-path-button-color: #999;
--copy-path-img-filter: invert(50%); --copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(65%); --copy-path-img-hover-filter: invert(65%);
--code-example-button-color: #7f7f7f;
--code-example-button-hover-color: #a5a5a5;
--codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-hover-color: rgb(255, 142, 0);
@ -2753,6 +2749,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--copy-path-button-color: #fff; --copy-path-button-color: #fff;
--copy-path-img-filter: invert(70%); --copy-path-img-filter: invert(70%);
--copy-path-img-hover-filter: invert(100%); --copy-path-img-hover-filter: invert(100%);
--code-example-button-color: #b2b2b2;
--code-example-button-hover-color: #fff;
--codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-hover-color: rgb(255, 142, 0);

View File

@ -1855,8 +1855,13 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
// Since the button will be added, no need to keep this listener around. // Since the button will be added, no need to keep this listener around.
elem.removeEventListener("mouseover", addCopyButton); elem.removeEventListener("mouseover", addCopyButton);
const parent = document.createElement("div"); // If this is a scrapped example, there will already be a "button-holder" element.
let parent = elem.querySelector(".button-holder");
if (!parent) {
parent = document.createElement("div");
parent.className = "button-holder"; parent.className = "button-holder";
}
const runButton = elem.querySelector(".test-arrow"); const runButton = elem.querySelector(".test-arrow");
if (runButton !== null) { if (runButton !== null) {
// If there is a run button, we move it into the same div. // If there is a run button, we move it into the same div.

View File

@ -13,7 +13,7 @@
// Scroll code block to the given code location // Scroll code block to the given code location
function scrollToLoc(elt, loc, isHidden) { function scrollToLoc(elt, loc, isHidden) {
const lines = elt.querySelector(".src-line-numbers"); const lines = elt.querySelector(".src-line-numbers > pre");
let scrollOffset; let scrollOffset;
// If the block is greater than the size of the viewer, // If the block is greater than the size of the viewer,
@ -24,8 +24,7 @@
const line = Math.max(0, loc[0] - 1); const line = Math.max(0, loc[0] - 1);
scrollOffset = lines.children[line].offsetTop; scrollOffset = lines.children[line].offsetTop;
} else { } else {
const wrapper = elt.querySelector(".code-wrapper"); const halfHeight = elt.offsetHeight / 2;
const halfHeight = wrapper.offsetHeight / 2;
const offsetTop = lines.children[loc[0]].offsetTop; const offsetTop = lines.children[loc[0]].offsetTop;
const lastLine = lines.children[loc[1]]; const lastLine = lines.children[loc[1]];
const offsetBot = lastLine.offsetTop + lastLine.offsetHeight; const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
@ -33,7 +32,7 @@
scrollOffset = offsetMid - halfHeight; scrollOffset = offsetMid - halfHeight;
} }
lines.scrollTo(0, scrollOffset); lines.parentElement.scrollTo(0, scrollOffset);
elt.querySelector(".rust").scrollTo(0, scrollOffset); elt.querySelector(".rust").scrollTo(0, scrollOffset);
} }

View File

@ -0,0 +1,33 @@
<div class="scraped-example{% if !info.needs_expansion +%} expanded{% endif %}" data-locs="{{info.locations}}"> {# #}
<div class="scraped-example-title">
{{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
</div>
<div class="example-wrap"> {# #}
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
Do not show "1 2 3 4 5 ..." in web search results. #}
<div class="src-line-numbers" data-nosnippet> {# #}
<pre>
{% for line in lines.clone() %}
{# ~#}
<span>{{line|safe}}</span>
{% endfor %}
</pre> {# #}
</div> {# #}
<pre class="rust"> {# #}
<code>
{{code_html|safe}}
</code> {# #}
</pre> {# #}
{% if info.needs_prev_next_buttons || info.needs_expansion %}
<div class="button-holder">
{% if info.needs_prev_next_buttons %}
<button class="prev">&pr;</button> {# #}
<button class="next">&sc;</button>
{% endif %}
{% if info.needs_expansion %}
<button class="expand">&varr;</button>
{% endif %}
</div>
{% endif %}
</div> {# #}
</div> {# #}

View File

@ -1,21 +1,15 @@
<div class="example-wrap"> {# #} <div class="example-wrap">
{# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
Do not show "1 2 3 4 5 ..." in web search results. #} Do not show "1 2 3 4 5 ..." in web search results. #}
<div data-nosnippet><pre class="src-line-numbers"> <div data-nosnippet><pre class="src-line-numbers">
{% for line in lines.clone() %} {% for line in lines.clone() %}
{% if embedded %} {# ~#}
<span>{{line|safe}}</span>
{%~ else %}
<a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a> <a href="#{{line|safe}}" id="{{line|safe}}">{{line|safe}}</a>
{%~ endif %}
{% endfor %} {% endfor %}
</pre></div> {# #} </pre></div> {# #}
<pre class="rust"> {# #} <pre class="rust"> {# #}
<code> <code>
{% if needs_expansion %}
<button class="expand">&varr;</button>
{% endif %}
{{code_html|safe}} {{code_html|safe}}
</code> {# #} </code> {# #}
</pre> {# #} </pre> {# #}
</div> </div> {# #}

View File

@ -94,3 +94,24 @@ call-function: ("check-buttons",{
"filter": "invert(0.5)", "filter": "invert(0.5)",
"filter_hover": "invert(0.35)", "filter_hover": "invert(0.35)",
}) })
define-function: (
"check-buttons-position",
[pre_selector],
block {
move-cursor-to: |pre_selector| + " .rust:not(.item-decl)"
store-position: (|pre_selector| + " .rust:not(.item-decl)", {"x": x, "y": y})
assert-position: (|pre_selector| + " .rust:not(.item-decl) + .button-holder", {
"y": |y| + 4,
})
}
)
call-function: ("check-buttons-position", {"pre_selector": ".example-wrap"})
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
// We should work as well for scraped examples.
call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"})
// And also when the scraped example "title" goes above.
set-window-size: (600, 600)
call-function: ("check-buttons-position", {"pre_selector": ".scraped-example .example-wrap"})

View File

@ -5,6 +5,18 @@ go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
// We check that without this setting, there is no line number displayed. // We check that without this setting, there is no line number displayed.
assert-false: "pre.example-line-numbers" assert-false: "pre.example-line-numbers"
// All corners should be rounded.
assert-css: (
".example-wrap .rust",
{
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
},
ALL,
)
// We set the setting to show the line numbers on code examples. // We set the setting to show the line numbers on code examples.
set-local-storage: {"rustdoc-line-numbers": "true"} set-local-storage: {"rustdoc-line-numbers": "true"}
reload: reload:
@ -29,9 +41,21 @@ define-function: (
"margin": "0px", "margin": "0px",
"padding": "14px 8px", "padding": "14px 8px",
"text-align": "right", "text-align": "right",
// There should not be a radius on the right of the line numbers.
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "0px",
"border-bottom-right-radius": "0px",
}, },
ALL, ALL,
) )
// There should not be a radius on the left of the line numbers.
assert-css: ("pre.example-line-numbers + .rust", {
"border-top-left-radius": "0px",
"border-bottom-left-radius": "0px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
})
}, },
) )
call-function: ("check-colors", { call-function: ("check-colors", {
@ -64,7 +88,56 @@ wait-for: 100 // wait-for-false does not exist
assert-false: "pre.example-line-numbers" assert-false: "pre.example-line-numbers"
assert-local-storage: {"rustdoc-line-numbers": "false" } assert-local-storage: {"rustdoc-line-numbers": "false" }
// Check that the rounded corners are back.
assert-css: (
".example-wrap .rust",
{
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
},
ALL,
)
// Finally, turn it on again. // Finally, turn it on again.
click: "input#line-numbers" click: "input#line-numbers"
wait-for: "pre.example-line-numbers" wait-for: "pre.example-line-numbers"
assert-local-storage: {"rustdoc-line-numbers": "true" } assert-local-storage: {"rustdoc-line-numbers": "true" }
// Same check with scraped examples line numbers.
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
assert-css: (
".scraped-example .src-line-numbers > pre",
{
// There should not be a radius on the right of the line numbers.
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "0px",
"border-bottom-right-radius": "0px",
},
ALL,
)
assert-css: (
".scraped-example .src-line-numbers",
{
// There should not be a radius on the right of the line numbers.
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "0px",
"border-bottom-right-radius": "0px",
},
ALL,
)
assert-css: (
".scraped-example .rust",
{
// There should not be a radius on the left of the code.
"border-top-left-radius": "0px",
"border-bottom-left-radius": "0px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
},
ALL,
)

View File

@ -3,29 +3,53 @@
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html" go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
// The next/prev buttons vertically scroll the code viewport between examples // The next/prev buttons vertically scroll the code viewport between examples
store-property: (".scraped-example-list > .scraped-example pre", {"scrollTop": initialScrollTop}) move-cursor-to: ".scraped-example-list > .scraped-example"
store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
"scrollTop": initialScrollTop,
})
assert-property: (".scraped-example-list > .scraped-example .rust", {
"scrollTop": |initialScrollTop|,
})
focus: ".scraped-example-list > .scraped-example .next" focus: ".scraped-example-list > .scraped-example .next"
press-key: "Enter" press-key: "Enter"
assert-property-false: (".scraped-example-list > .scraped-example pre", { assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
"scrollTop": |initialScrollTop|
}, NEAR)
assert-property-false: (".scraped-example-list > .scraped-example .rust", {
"scrollTop": |initialScrollTop| "scrollTop": |initialScrollTop|
}, NEAR) }, NEAR)
focus: ".scraped-example-list > .scraped-example .prev" focus: ".scraped-example-list > .scraped-example .prev"
press-key: "Enter" press-key: "Enter"
assert-property: (".scraped-example-list > .scraped-example pre", { assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
"scrollTop": |initialScrollTop|
}, NEAR)
assert-property: (".scraped-example-list > .scraped-example .rust", {
"scrollTop": |initialScrollTop| "scrollTop": |initialScrollTop|
}, NEAR) }, NEAR)
// The expand button increases the scrollHeight of the minimized code viewport // The expand button increases the scrollHeight of the minimized code viewport
store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight}) store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": smallOffsetHeight})
assert-property-false: (".scraped-example-list > .scraped-example pre", { assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
"scrollHeight": |smallOffsetHeight|
}, NEAR)
assert-property: (".scraped-example-list > .scraped-example .rust", {
"scrollHeight": |smallOffsetHeight| "scrollHeight": |smallOffsetHeight|
}, NEAR) }, NEAR)
focus: ".scraped-example-list > .scraped-example .expand" focus: ".scraped-example-list > .scraped-example .expand"
press-key: "Enter" press-key: "Enter"
assert-property-false: (".scraped-example-list > .scraped-example pre", { assert-property-false: (".scraped-example-list > .scraped-example .src-line-numbers", {
"offsetHeight": |smallOffsetHeight| "offsetHeight": |smallOffsetHeight|
}, NEAR) }, NEAR)
store-property: (".scraped-example-list > .scraped-example pre", {"offsetHeight": fullOffsetHeight}) assert-property-false: (".scraped-example-list > .scraped-example .rust", {
assert-property: (".scraped-example-list > .scraped-example pre", { "offsetHeight": |smallOffsetHeight|
}, NEAR)
store-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
"offsetHeight": fullOffsetHeight,
})
assert-property: (".scraped-example-list > .scraped-example .rust", {
"offsetHeight": |fullOffsetHeight|,
"scrollHeight": |fullOffsetHeight|,
})
assert-property: (".scraped-example-list > .scraped-example .src-line-numbers", {
"scrollHeight": |fullOffsetHeight| "scrollHeight": |fullOffsetHeight|
}, NEAR) }, NEAR)

View File

@ -10,10 +10,10 @@ define-function: (
block { block {
call-function: ("switch-theme", {"theme": |theme|}) call-function: ("switch-theme", {"theme": |theme|})
wait-for: ".more-examples-toggle" wait-for: ".more-examples-toggle"
assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { assert-css: (".scraped-example .rust span.highlight:not(.focus)", {
"background-color": |highlight|, "background-color": |highlight|,
}, ALL) }, ALL)
assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", { assert-css: (".scraped-example .rust span.highlight.focus", {
"background-color": |highlight_focus|, "background-color": |highlight_focus|,
}, ALL) }, ALL)
@ -67,11 +67,11 @@ define-function: (
[theme, background_color_start, background_color_end], [theme, background_color_start, background_color_end],
block { block {
call-function: ("switch-theme", {"theme": |theme|}) call-function: ("switch-theme", {"theme": |theme|})
assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", { assert-css: (".scraped-example:not(.expanded) .example-wrap::before", {
"background-image": "linear-gradient(" + |background_color_start| + ", " + "background-image": "linear-gradient(" + |background_color_start| + ", " +
|background_color_end| + ")", |background_color_end| + ")",
}) })
assert-css: (".scraped-example:not(.expanded) .code-wrapper::after", { assert-css: (".scraped-example:not(.expanded) .example-wrap::after", {
"background-image": "linear-gradient(to top, " + |background_color_start| + ", " + "background-image": "linear-gradient(to top, " + |background_color_start| + ", " +
|background_color_end| + ")", |background_color_end| + ")",
}) })

View File

@ -1,48 +1,115 @@
// Check that the line number column has the correct layout. // Check that the line number column has the correct layout.
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html" go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
set-window-size: (1000, 1000)
// Check that it's not zero. // Check that it's not zero.
assert-property-false: ( assert-property-false: (
".more-scraped-examples .scraped-example .code-wrapper .src-line-numbers", ".more-scraped-examples .scraped-example .src-line-numbers",
{"clientWidth": "0"} {"clientWidth": "0"}
) )
// Check that examples with very long lines have the same width as ones that don't. // Check that examples with very long lines have the same width as ones that don't.
store-property: ( store-property: (
".more-scraped-examples .scraped-example:nth-child(2) .code-wrapper .src-line-numbers", ".more-scraped-examples .scraped-example:nth-child(2) .src-line-numbers",
{"clientWidth": clientWidth}, {"clientWidth": clientWidth},
) )
assert-property: ( assert-property: (
".more-scraped-examples .scraped-example:nth-child(3) .code-wrapper .src-line-numbers", ".more-scraped-examples .scraped-example:nth-child(3) .src-line-numbers",
{"clientWidth": |clientWidth|} {"clientWidth": |clientWidth|}
) )
assert-property: ( assert-property: (
".more-scraped-examples .scraped-example:nth-child(4) .code-wrapper .src-line-numbers", ".more-scraped-examples .scraped-example:nth-child(4) .src-line-numbers",
{"clientWidth": |clientWidth|} {"clientWidth": |clientWidth|}
) )
assert-property: ( assert-property: (
".more-scraped-examples .scraped-example:nth-child(5) .code-wrapper .src-line-numbers", ".more-scraped-examples .scraped-example:nth-child(5) .src-line-numbers",
{"clientWidth": |clientWidth|} {"clientWidth": |clientWidth|}
) )
assert-property: ( assert-property: (
".more-scraped-examples .scraped-example:nth-child(6) .code-wrapper .src-line-numbers", ".more-scraped-examples .scraped-example:nth-child(6) .src-line-numbers",
{"clientWidth": |clientWidth|} {"clientWidth": |clientWidth|}
) )
// The "title" should be located at the right bottom corner of the code example.
store-position: (".scraped-example .example-wrap", {"x": x, "y": y})
store-size: (".scraped-example .example-wrap", {"width": width, "height": height})
store-size: (".scraped-example .scraped-example-title", {
"width": title_width,
"height": title_height,
})
assert-position: (".scraped-example .scraped-example-title", {
"x": |x| + |width| - |title_width| - 5,
"y": |y| + |height| - |title_height| - 8,
})
// Check that the expand button works and also that line number aligns with code.
move-cursor-to: ".scraped-example .rust"
click: ".scraped-example .button-holder .expand"
wait-for: ".scraped-example.expanded"
// They should have the same y position.
compare-elements-position: (
".scraped-example.expanded .src-line-numbers pre span",
".scraped-example.expanded .rust code",
["y"],
)
// And they should have the same height.
compare-elements-size: (
".scraped-example.expanded .src-line-numbers",
".scraped-example.expanded .rust",
["height"],
)
// Collapse code again.
click: ".scraped-example .button-holder .expand"
// Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed // Check that for both mobile and desktop sizes, the buttons in scraped examples are displayed
// correctly. // correctly.
store-value: (offset_y, 4) store-value: (offset_y, 4)
// First with desktop // First with desktop
assert-position: (".scraped-example .code-wrapper", {"y": 226}) assert-position: (".scraped-example", {"y": 226})
assert-position: (".scraped-example .code-wrapper .prev", {"y": 226 + |offset_y|}) assert-position: (".scraped-example .prev", {"y": 226 + |offset_y|})
// Gradient background should be at the top of the code block.
assert-css: (".scraped-example .example-wrap::before", {"top": "0px"})
assert-css: (".scraped-example .example-wrap::after", {"bottom": "0px"})
// Then with mobile // Then with mobile
set-window-size: (600, 600) set-window-size: (600, 600)
assert-position: (".scraped-example .code-wrapper", {"y": 308}) store-size: (".scraped-example .scraped-example-title", {"height": title_height})
assert-position: (".scraped-example .code-wrapper .prev", {"y": 308 + |offset_y|}) assert-position: (".scraped-example", {"y": 284})
assert-position: (".scraped-example .prev", {"y": 284 + |offset_y| + |title_height|})
define-function: (
"check_title_and_code_position",
[],
block {
// Title should be above the code.
store-position: (".scraped-example .example-wrap .src-line-numbers", {"x": x, "y": y})
store-size: (".scraped-example .scraped-example-title", { "height": title_height })
assert-position: (".scraped-example .scraped-example-title", {
"x": |x|, // same X position.
"y": |y| - |title_height|,
})
// Line numbers should be right beside the code.
compare-elements-position: (
".scraped-example .example-wrap .src-line-numbers",
".scraped-example .example-wrap .rust",
["y"],
)
}
)
// Check that the title is now above the code.
call-function: ("check_title_and_code_position", {})
// Then with small mobile
set-window-size: (300, 300)
call-function: ("check_title_and_code_position", {})

View File

@ -23,6 +23,8 @@
--copy-path-button-color: #999; --copy-path-button-color: #999;
--copy-path-img-filter: invert(50%); --copy-path-img-filter: invert(50%);
--copy-path-img-hover-filter: invert(35%); --copy-path-img-hover-filter: invert(35%);
--code-example-button-color: #7f7f7f;
--code-example-button-hover-color: #a5a5a5;
--codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-hover-color: rgb(255, 0, 0);
--codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-error-color: rgba(255, 0, 0, .5);
--codeblock-ignore-hover-color: rgb(255, 142, 0); --codeblock-ignore-hover-color: rgb(255, 142, 0);