From bab13f55d63e8f55adf2453ceb9bba46f7942e38 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Aug 2021 17:14:15 +0200 Subject: [PATCH] Add toggle mechanism for docs.rs source sidebar --- src/web/metrics.rs | 1 + src/web/statics.rs | 18 ++++++++++ static/source.js | 41 +++++++++++++++++++++++ templates/crate/source.html | 17 +++++++--- templates/style/base.scss | 65 +++++++++++++++++++++++++++++++++++-- 5 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 static/source.js diff --git a/src/web/metrics.rs b/src/web/metrics.rs index 7978a4079..89a2d15f1 100644 --- a/src/web/metrics.rs +++ b/src/web/metrics.rs @@ -121,6 +121,7 @@ mod tests { ("/-/static/index.js", "static resource"), ("/-/static/menu.js", "static resource"), ("/-/static/keyboard.js", "static resource"), + ("/-/static/source.js", "static resource"), ("/-/static/opensearch.xml", "static resource"), ("/releases", "/releases"), ("/releases/feed", "static resource"), diff --git a/src/web/statics.rs b/src/web/statics.rs index 3a64eceee..f3f9a3d39 100644 --- a/src/web/statics.rs +++ b/src/web/statics.rs @@ -228,6 +228,24 @@ mod tests { }); } + #[test] + fn source_js() { + wrapper(|env| { + let web = env.frontend(); + + let resp = web.get("/-/static/source.js").send()?; + assert!(resp.status().is_success()); + assert_eq!( + resp.headers().get("Content-Type"), + Some(&"application/javascript".parse().unwrap()), + ); + assert!(resp.content_length().unwrap() > 10); + assert!(resp.text()?.contains("toggleSource")); + + Ok(()) + }); + } + #[test] fn static_files() { wrapper(|env| { diff --git a/static/source.js b/static/source.js new file mode 100644 index 000000000..9bd14cfac --- /dev/null +++ b/static/source.js @@ -0,0 +1,41 @@ +(function() { + var oldLabel; + + function showSourceFiles(button, sideMenu, sourceCode) { + button.title = oldLabel; + button.setAttribute("aria-label", button.title); + button.setAttribute("aria-expanded", "true"); + + sideMenu.classList.remove("collapsed"); + sourceCode.classList.remove("expanded"); + } + + function hideSourceFiles(button, sideMenu, sourceCode) { + button.title = "Show source sidebar"; + button.setAttribute("aria-label", button.title); + button.setAttribute("aria-expanded", "false"); + + sideMenu.classList.add("collapsed"); + sourceCode.classList.add("expanded"); + } + + function toggleSource(button) { + var sideMenu = document.getElementById("side-menu"); + var sourceCode = document.getElementById("source-code"); + + if (sideMenu.classList.contains("collapsed")) { + showSourceFiles(button, sideMenu, sourceCode); + } else { + hideSourceFiles(button, sideMenu, sourceCode); + } + } + + document.addEventListener("DOMContentLoaded", function(event) { + var toggleSourceButton = document.querySelector("li.toggle-source button"); + oldLabel = toggleSourceButton.getAttribute("aria-label"); + + toggleSourceButton.addEventListener("click", function() { + toggleSource(toggleSourceButton); + }); + }); +})(); diff --git a/templates/crate/source.html b/templates/crate/source.html index 4312e924d..f9ae49760 100644 --- a/templates/crate/source.html +++ b/templates/crate/source.html @@ -24,13 +24,19 @@ {%- block body -%}
-
+
    + {# If we are displaying a file, we also add a button to hide the file sidebar #} + {% if file_content %} +
  • + +
  • + {% endif %} {# If this isn't the root folder, show a 'back' button #} {%- if show_parent_link -%}
  • - {{ "folder-open" | far(fw=true) }} .. + {{ "folder-open" | far(fw=true) }} ..
  • {%- endif -%} @@ -88,7 +94,7 @@ {{ "file-archive" | far(fw=true) }} {%- endif -%} - {{ file.name }} + {{ file.name }} {%- endfor -%} @@ -98,7 +104,7 @@ {# If the file has content, then display it in a codeblock #} {%- if file_content -%} -
    +
    {{ file_content }}
    {%- endif -%} @@ -114,4 +120,7 @@ {%- block javascript -%} {# Highlight.js JavaScript #} {{ macros::highlight_js(languages=["rust", "ini", "markdown"]) }} + {% if file_content %} + + {% endif %} {%- endblock javascript -%} diff --git a/templates/style/base.scss b/templates/style/base.scss index 5e37ce8b2..1e5d3848a 100644 --- a/templates/style/base.scss +++ b/templates/style/base.scss @@ -438,7 +438,7 @@ div.package-page-container { margin-top: 0; } - a.pure-menu-link { + .pure-menu-link { font-size: 14px; color: var(--color-standard); white-space: nowrap; @@ -447,7 +447,7 @@ div.package-page-container { padding: 7px 8px; } - a.pure-menu-link:hover { + .pure-menu-link:hover { background-color: var(--color-background-code); } @@ -759,3 +759,64 @@ h3 > code, h4 > code { display: inline-block; } + +ul.pure-menu-list { + li.toggle-source { + cursor: pointer; + border: 1px solid var(--color-border); + display: none; + } +} + +@media screen and (min-width: 35.5em) { + ul.pure-menu-list { + li.toggle-source { + display: list-item; + + button { + font-size: 14px; + color: var(--color-standard); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + padding: 7px 8px; + background: transparent; + border: 0; + width: 100%; + } + + .right { + display: none; + } + } + } + + #side-menu.collapsed { + max-width: 46px; + + ul { + li:not(.toggle-source), .text { + display: none; + } + li.toggle-source { + .left { + display: none; + } + .right { + display: inline-block; + margin-left: -4px; + } + } + } + } + + #source-code { + pre { + margin-top: 0; + } + + &.expanded { + width: calc(100% - 46px); + } + } +}