diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 642265f5f6bef..d0e3dd339855e 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -51,6 +51,8 @@ use crate::html::highlight; use crate::html::length_limit::HtmlWithLimit; use crate::html::render::small_url_encode; use crate::html::toc::TocBuilder; +use crate::html::static_files; +use crate::html::layout::Page; use pulldown_cmark::{ html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag, @@ -270,9 +272,15 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { format!( "
\
\
+                                     \
                                      {text}\
                                  
\
", + static_root_path = &get_static_root_path(), + clipboard_svg = &static_files::STATIC_FILES.clipboard_svg, added_classes = added_classes.join(" "), text = Escape(&original_text), ) diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index d4b1da71b40a0..b79f94514c8e2 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -5,6 +5,7 @@ use crate::error::Error; use crate::html::format; use crate::html::highlight; use crate::html::layout; +use crate::html::Page; use crate::html::render::Context; use crate::visit::DocVisitor; @@ -315,6 +316,7 @@ pub(crate) fn print_src( needs_expansion: bool, lines: RangeInclusive, code_html: Code, + static_root_path: &'a str, } let lines = s.lines().count(); let (embedded, needs_expansion, lines) = match source_context { @@ -335,5 +337,6 @@ pub(crate) fn print_src( ); Ok(()) }); - Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap(); + let static_root_path = get_static_root_path(); + Source { embedded, needs_expansion, lines, code_html: code, static_root_path }.render_into(&mut writer).unwrap(); } diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css index f425f3ec95c31..da752c981d270 100644 --- a/src/librustdoc/html/static/css/noscript.css +++ b/src/librustdoc/html/static/css/noscript.css @@ -9,7 +9,7 @@ rules. margin-left: 0 !important; } -#copy-path, #sidebar-button, .sidebar-resizer { +#copy-path, #sidebar-button, .sidebar-resizer, .copy-code { /* It requires JS to work so no need to display it in this case. */ display: none !important; } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index cd53fcb8b7c16..954e032784b95 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1596,6 +1596,24 @@ a.tooltip:hover::after { height: 22px; } +.copy-code { + width: 32px; + height: 30px; + float: right; + opacity: 0; + transition: opacity ease 0.3s; + background: var(--code-block-background-color); + outline: 1px solid var(--main-color); + border-radius: 5px; + padding: 5px 7px 4px 8px; + z-index: 1; + position: sticky; +} + +.copy-code > img { + filter: var(--copy-code-img-filter); +} + #copy-path { color: var(--copy-path-button-color); background: var(--main-background-color); @@ -2329,6 +2347,7 @@ in src-script.js and main.js --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(35%); + --copy-code-img-filter: invert(20%); --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -2434,6 +2453,7 @@ in src-script.js and main.js --copy-path-button-color: #999; --copy-path-img-filter: invert(50%); --copy-path-img-hover-filter: invert(65%); + --copy-code-img-filter: invert(50%); --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); @@ -2546,6 +2566,7 @@ Original by Dempfi (https://github.com/dempfi/ayu) --copy-path-button-color: #fff; --copy-path-img-filter: invert(70%); --copy-path-img-hover-filter: invert(100%); + --copy-code-img-filter: invert(50%); --codeblock-error-hover-color: rgb(255, 0, 0); --codeblock-error-color: rgba(255, 0, 0, .5); --codeblock-ignore-hover-color: rgb(255, 142, 0); diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 88901191cda25..49bfd41f9660a 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1734,6 +1734,37 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm resizer.addEventListener("pointerdown", initResize, false); }()); +// This section handles the copy buttons that appears in top right corner of the code blocks +(function() { + let preElements = document.querySelectorAll("pre:has(code)"); + preElements.forEach(function(pre, index) { + let resetTimeout = null; + let copyBtn = pre.querySelector("button[class='copy-code']"); + let icon = copyBtn.innerHTML; + pre.addEventListener("mouseenter", function() { + copyBtn.style.opacity = "1"; + copyBtn.addEventListener("click", function() { + let code = pre.querySelector("code"); + let summary = code.querySelector("summary"); + let content = code.textContent; + content = content.replace(summary.textContent, ""); + navigator.clipboard.writeText(content).then(function() { + copyBtn.textContent = "✓"; + if (resetTimeout !== null) { + clearTimeout(resetTimeout); + } + resetTimeout = setTimeout(function() { + copyBtn.innerHTML = icon; + }, 1000); + }); + }); + }); + pre.addEventListener("mouseleave", function() { + copyBtn.style.opacity = "0"; + }); + }); +}()); + // This section handles the copy button that appears next to the path breadcrumbs (function() { let reset_button_timeout = null; diff --git a/src/librustdoc/html/templates/source.html b/src/librustdoc/html/templates/source.html index 42d01277db2c2..08a425e235cd1 100644 --- a/src/librustdoc/html/templates/source.html +++ b/src/librustdoc/html/templates/source.html @@ -11,6 +11,11 @@ {% endfor %} {# #}
 {# #}
+         {# #}
         
             {% if needs_expansion %}