Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustdoc/html/static/css/noscript.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ rules.
margin-left: 0 !important;
}

#copy-path, #sidebar-button, .sidebar-resizer {
#sidebar-button, .sidebar-resizer {
/* It requires JS to work so no need to display it in this case. */
display: none !important;
}
Expand Down
57 changes: 32 additions & 25 deletions src/librustdoc/html/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2113,34 +2113,41 @@ function preLoadCss(cssUrl) {
}, 1000);
}

// Copy button that appears next to the path breadcrumbs.
const but = document.getElementById("copy-path");
if (!but) {
return;
}
but.onclick = () => {
// We get the path from the "breadcrumbs" and the actual item name.
let path = "";
// @ts-expect-error
const heading = document.getElementById(MAIN_ID).querySelector(".main-heading");

if (heading) {
const breadcrumbs = heading.querySelector(".rustdoc-breadcrumbs");
if (breadcrumbs) {
// @ts-expect-error
path = breadcrumbs.innerText;
if (path.length > 0) {
path += "::";
const itemPath = nonnull(document.getElementById(MAIN_ID)).querySelector(".main-heading h1");
// The best way to check it's a page where we should generate the "copy path" button is to
// check if there is a `<span>` in the `<h1>`.
if (itemPath && itemPath.querySelector("span")) {
// Copy button that appears next to the path breadcrumbs.
const but = document.createElement("button");
but.id = "copy-path";
but.setAttribute("title", "Copy item path to clipboard");
but.innerText = "Copy item path";

but.onclick = () => {
const heading = nonnull(
document.getElementById(MAIN_ID)).querySelector(".main-heading");
if (heading) {
// We get the path from the "breadcrumbs" and the actual item name.
let path = "";

const breadcrumbs = heading.querySelector(".rustdoc-breadcrumbs");
if (breadcrumbs) {
// @ts-expect-error
path = breadcrumbs.innerText;
if (path.length > 0) {
path += "::";
}
}
}

// @ts-expect-error
path += heading.querySelector("h1 > span").innerText;
// @ts-expect-error
path += heading.querySelector("h1 > span").innerText;

copyContentToClipboard(path);
copyButtonAnimation(but);
}
};
copyContentToClipboard(path);
copyButtonAnimation(but);
}
};
itemPath.appendChild(but);
}

/**
* Copy buttons on code examples.
Expand Down
5 changes: 1 addition & 4 deletions src/librustdoc/html/templates/print_item.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@
{% endif %}
<h1>
{{typ}}
<span{% if item_type != "mod" +%} class="{{item_type}}"{% endif %}>
<span {% if item_type != "mod" +%} class="{{item_type}}"{% endif %}>
{{name|wrapped|safe}}
</span>&nbsp;{# #}
<button id="copy-path" title="Copy item path to clipboard"> {# #}
Copy item path {# #}
</button> {# #}
</h1> {# #}
<rustdoc-toolbar></rustdoc-toolbar> {# #}
<span class="sub-heading">
Expand Down
48 changes: 46 additions & 2 deletions tests/rustdoc-gui/copy-path.goml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Checks that the "copy path" button is not triggering JS error and its display
// isn't broken and the copied path is as expected.
// Checks that the "copy path" button is not triggering JS error and its display isn't broken and
// the copied path is as expected. Also checks that the button is only present on the expected
// pages.
go-to: "file://" + |DOC_PATH| + "/test_docs/foreign_impl_order/trait.Foo.html"
permissions: ["clipboard-read"]

// We ensure that the clipboard is empty.
assert-clipboard: ""

// First we store the size of the button before we click on it.
wait-for: "#copy-path"
store-size: ("#copy-path", {"width": width, "height": height})
click: "#copy-path"
// We wait for the new text to appear.
Expand All @@ -22,6 +24,7 @@ assert-size: ("#copy-path:not(.clicked)", {"width": |width|, "height": |height|}

// Check the path for a module.
go-to: "file://" + |DOC_PATH| + "/test_docs/foreign_impl_order/index.html"
wait-for: "#copy-path"
click: "#copy-path"
// We wait for the new text to appear.
wait-for: "#copy-path.clicked"
Expand All @@ -30,8 +33,49 @@ assert-clipboard: "test_docs::foreign_impl_order"

// Check the path for the crate.
go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
wait-for: "#copy-path"
click: "#copy-path"
// We wait for the new text to appear.
wait-for: "#copy-path.clicked"
// We check that the clipboard value is the expected one.
assert-clipboard: "test_docs"

// Now check the presence of the "copy code" button. Above we already checked for items, crate

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“Copy code”? Don’t you mean “copy path”?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. ^^'

// and modules.
define-function: ("check-copy-path-presence", [path], block {
go-to: "file://" + |DOC_PATH| + "/test_docs/" + |path|
wait-for: "#copy-path"
})

// Keyword
call-function: ("check-copy-path-presence", {"path": "keyword.for.html"})
// Attribute
call-function: ("check-copy-path-presence", {"path": "attribute.forbid.html"})
// Macro
call-function: ("check-copy-path-presence", {"path": "macro.attr_macro.html"})
// Constant
call-function: ("check-copy-path-presence", {"path": "constant.CONST.html"})

// And now we check its absence.
define-function: ("check-copy-path-absence", [path], block {
go-to: "file://" + |DOC_PATH| + "/" + |path|
expect-failure: true
wait-for: "#copy-path"
expect-failure: false
})

// To prevent waiting for too long, we set the maximum time for "wait-for" to 1 second.
set-timeout: 1000

// Source code page.
call-function: ("check-copy-path-absence", {"path": "src/test_docs/lib.rs.html"})
// Settings page.
call-function: ("check-copy-path-absence", {"path": "settings.html"})
// Help page.
call-function: ("check-copy-path-absence", {"path": "help.html"})
// All items page.
call-function: ("check-copy-path-absence", {"path": "test_docs/all.html"})

// Check the button is not present if javascript is disabled (since it's generated with JS...).
javascript: false
call-function: ("check-copy-path-absence", {"path": "test_docs/index.html"})
Loading