diff --git a/src/utils/html.rs b/src/utils/html.rs
index 961b5eea3..738a2dbf3 100644
--- a/src/utils/html.rs
+++ b/src/utils/html.rs
@@ -2,7 +2,7 @@ use crate::web::page::TemplateData;
use lol_html::errors::RewritingError;
use tera::Context;
-/// Rewrite a rustdoc page to have the docs.rs header
+/// Rewrite a rustdoc page to have the docs.rs topbar
///
/// Given a rustdoc HTML page and a context to serialize it with,
/// render the `rustdoc/` templates with the `html`.
@@ -21,7 +21,7 @@ pub(crate) fn rewrite_lol(
let tera_head = templates.render("rustdoc/head.html", &ctx).unwrap();
let tera_vendored_css = templates.render("rustdoc/vendored.html", &ctx).unwrap();
let tera_body = templates.render("rustdoc/body.html", &ctx).unwrap();
- let tera_rustdoc_header = templates.render("rustdoc/header.html", &ctx).unwrap();
+ let tera_rustdoc_topbar = templates.render("rustdoc/topbar.html", &ctx).unwrap();
// Append `style.css` stylesheet after all head elements.
let head_handler = |head: &mut Element| {
@@ -54,10 +54,10 @@ pub(crate) fn rewrite_lol(
rustdoc_body_class.set_tag_name("div")?;
// Prepend the tera content
rustdoc_body_class.prepend(&tera_body, ContentType::Html);
- // Wrap the tranformed body and rustdoc header into a
element
+ // Wrap the tranformed body and topbar into a element
rustdoc_body_class.before("", ContentType::Html);
- // Insert the header outside of the rustdoc div
- rustdoc_body_class.before(&tera_rustdoc_header, ContentType::Html);
+ // Insert the topbar outside of the rustdoc div
+ rustdoc_body_class.before(&tera_rustdoc_topbar, ContentType::Html);
// Finalize body with
rustdoc_body_class.after("", ContentType::Html);
diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs
index 4b2cd0d1b..15cc60ba8 100644
--- a/src/web/crate_details.rs
+++ b/src/web/crate_details.rs
@@ -39,8 +39,6 @@ pub struct CrateDetails {
github_issues: Option,
pub(crate) metadata: MetaData,
is_library: bool,
- yanked: bool,
- pub(crate) doc_targets: Vec,
license: Option,
documentation_url: Option,
total_items: Option,
@@ -144,18 +142,8 @@ impl CrateDetails {
rustdoc_status: krate.get("rustdoc_status"),
target_name: krate.get("target_name"),
default_target: krate.get("default_target"),
- };
-
- let doc_targets = {
- let data: Value = krate.get("doc_targets");
- data.as_array()
- .map(|array| {
- array
- .iter()
- .filter_map(|item| item.as_str().map(|s| s.to_owned()))
- .collect()
- })
- .unwrap_or_else(Vec::new)
+ doc_targets: MetaData::parse_doc_targets(krate.get("doc_targets")),
+ yanked: krate.get("yanked"),
};
let documented_items: Option = krate.get("documented_items");
@@ -189,8 +177,6 @@ impl CrateDetails {
github_issues: krate.get("github_issues"),
metadata,
is_library: krate.get("is_library"),
- yanked: krate.get("yanked"),
- doc_targets,
license: krate.get("license"),
documentation_url: krate.get("documentation_url"),
documented_items: documented_items.map(|v| v as f32),
diff --git a/src/web/mod.rs b/src/web/mod.rs
index 64136a08f..642251f79 100644
--- a/src/web/mod.rs
+++ b/src/web/mod.rs
@@ -3,6 +3,7 @@
pub(crate) mod page;
use log::{debug, info};
+use serde_json::Value;
/// ctry! (cratesfyitry) is extremely similar to try! and itry!
/// except it returns an error page response instead of plain Err.
@@ -542,6 +543,8 @@ pub(crate) struct MetaData {
pub(crate) target_name: Option,
pub(crate) rustdoc_status: bool,
pub(crate) default_target: String,
+ pub(crate) doc_targets: Vec,
+ pub(crate) yanked: bool,
}
impl MetaData {
@@ -553,7 +556,9 @@ impl MetaData {
releases.description,
releases.target_name,
releases.rustdoc_status,
- releases.default_target
+ releases.default_target,
+ releases.doc_targets,
+ releases.yanked
FROM releases
INNER JOIN crates ON crates.id = releases.crate_id
WHERE crates.name = $1 AND releases.version = $2",
@@ -570,8 +575,22 @@ impl MetaData {
target_name: row.get(3),
rustdoc_status: row.get(4),
default_target: row.get(5),
+ doc_targets: MetaData::parse_doc_targets(row.get(6)),
+ yanked: row.get(7),
})
}
+
+ fn parse_doc_targets(targets: Value) -> Vec {
+ targets
+ .as_array()
+ .map(|array| {
+ array
+ .iter()
+ .filter_map(|item| item.as_str().map(|s| s.to_owned()))
+ .collect()
+ })
+ .unwrap_or_else(Vec::new)
+ }
}
#[derive(Debug, Clone, PartialEq, Serialize)]
@@ -840,6 +859,11 @@ mod test {
target_name: None,
rustdoc_status: true,
default_target: "x86_64-unknown-linux-gnu".to_string(),
+ doc_targets: vec![
+ "x86_64-unknown-linux-gnu".to_string(),
+ "arm64-unknown-linux-gnu".to_string(),
+ ],
+ yanked: false,
};
let correct_json = json!({
@@ -848,19 +872,29 @@ mod test {
"description": "serde does stuff",
"target_name": null,
"rustdoc_status": true,
- "default_target": "x86_64-unknown-linux-gnu"
+ "default_target": "x86_64-unknown-linux-gnu",
+ "doc_targets": [
+ "x86_64-unknown-linux-gnu",
+ "arm64-unknown-linux-gnu",
+ ],
+ "yanked": false,
});
assert_eq!(correct_json, serde_json::to_value(&metadata).unwrap());
- metadata.target_name = Some("x86_64-apple-darwin".to_string());
+ metadata.target_name = Some("serde_lib_name".to_string());
let correct_json = json!({
"name": "serde",
"version": "1.0.0",
"description": "serde does stuff",
- "target_name": "x86_64-apple-darwin",
+ "target_name": "serde_lib_name",
"rustdoc_status": true,
- "default_target": "x86_64-unknown-linux-gnu"
+ "default_target": "x86_64-unknown-linux-gnu",
+ "doc_targets": [
+ "x86_64-unknown-linux-gnu",
+ "arm64-unknown-linux-gnu",
+ ],
+ "yanked": false,
});
assert_eq!(correct_json, serde_json::to_value(&metadata).unwrap());
@@ -870,9 +904,14 @@ mod test {
"name": "serde",
"version": "1.0.0",
"description": null,
- "target_name": "x86_64-apple-darwin",
+ "target_name": "serde_lib_name",
"rustdoc_status": true,
- "default_target": "x86_64-unknown-linux-gnu"
+ "default_target": "x86_64-unknown-linux-gnu",
+ "doc_targets": [
+ "x86_64-unknown-linux-gnu",
+ "arm64-unknown-linux-gnu",
+ ],
+ "yanked": false,
});
assert_eq!(correct_json, serde_json::to_value(&metadata).unwrap());
diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs
index 063e11df3..99a32b829 100644
--- a/src/web/rustdoc.rs
+++ b/src/web/rustdoc.rs
@@ -5,7 +5,7 @@ use crate::{
utils,
web::{
crate_details::CrateDetails, error::Nope, file::File, match_version,
- metrics::RenderingTimesRecorder, redirect_base, MatchSemver,
+ metrics::RenderingTimesRecorder, redirect_base, MatchSemver, MetaData,
},
Config, Metrics, Storage,
};
@@ -186,6 +186,7 @@ struct RustdocPage {
is_latest_version: bool,
is_prerelease: bool,
krate: CrateDetails,
+ metadata: MetaData,
}
impl RustdocPage {
@@ -390,7 +391,7 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult {
"/{}/{}/{}",
name,
latest_version,
- path_for_version(&latest_path, &krate.doc_targets, &storage, &config)
+ path_for_version(&latest_path, &krate.metadata.doc_targets, &storage, &config)
)
} else {
format!("/crate/{}/{}", name, latest_version)
@@ -407,7 +408,12 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult {
// Drop the `rustdoc/:crate/:version[/:platform]` prefix
inner_path.drain(..3).for_each(drop);
- let target = if inner_path.len() > 1 && krate.doc_targets.iter().any(|s| s == inner_path[0])
+ let target = if inner_path.len() > 1
+ && krate
+ .metadata
+ .doc_targets
+ .iter()
+ .any(|s| s == inner_path[0])
{
let mut target = inner_path.remove(0).to_string();
target.push('/');
@@ -427,6 +433,7 @@ pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult {
inner_path,
is_latest_version,
is_prerelease,
+ metadata: krate.metadata.clone(),
krate,
}
.into_response(&file.0.content, config.max_parse_memory, req, &path)
@@ -513,7 +520,12 @@ pub fn target_redirect_handler(req: &mut Request) -> IronResult {
file_path
};
- let path = path_for_version(&file_path, &crate_details.doc_targets, &storage, &config);
+ let path = path_for_version(
+ &file_path,
+ &crate_details.metadata.doc_targets,
+ &storage,
+ &config,
+ );
let url = format!(
"{base}/{name}/{version}/{path}",
base = base,
diff --git a/src/web/source.rs b/src/web/source.rs
index 587092fe1..30bb48fa7 100644
--- a/src/web/source.rs
+++ b/src/web/source.rs
@@ -56,7 +56,9 @@ impl FileList {
releases.target_name,
releases.rustdoc_status,
releases.files,
- releases.default_target
+ releases.default_target,
+ releases.doc_targets,
+ releases.yanked
FROM releases
LEFT OUTER JOIN crates ON crates.id = releases.crate_id
WHERE crates.name = $1 AND releases.version = $2",
@@ -133,6 +135,8 @@ impl FileList {
target_name: rows[0].get(3),
rustdoc_status: rows[0].get(4),
default_target: rows[0].get(6),
+ doc_targets: MetaData::parse_doc_targets(rows[0].get(7)),
+ yanked: rows[0].get(8),
},
files: file_list,
})
diff --git a/templates/base.html b/templates/base.html
index a8a61d433..498035470 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -24,7 +24,9 @@
- {%- include "header/topbar.html" -%}
+ {%- block topbar -%}
+ {%- include "header/topbar.html" -%}
+ {%- endblock topbar -%}
{%- block header %}{% endblock header -%}
diff --git a/templates/crate/builds.html b/templates/crate/builds.html
index 47d5520fd..e3b011df2 100644
--- a/templates/crate/builds.html
+++ b/templates/crate/builds.html
@@ -5,6 +5,16 @@
{{ macros::doc_title(name=metadata.name, version=metadata.version) }}
{%- endblock title -%}
+{%- block topbar -%}
+ {%- set latest_version = "" -%}
+ {%- set latest_path = "" -%}
+ {%- set target = "" -%}
+ {%- set inner_path = metadata.target_name ~ "/index.html" -%}
+ {%- set is_latest_version = true -%}
+ {%- set is_prerelease = false -%}
+ {%- include "rustdoc/topbar.html" -%}
+{%- endblock topbar -%}
+
{%- block header -%}
{{ navigation::package_navigation(metadata=metadata, active_tab="builds") }}
{%- endblock header -%}
diff --git a/templates/crate/details.html b/templates/crate/details.html
index b3a3639ad..b1d8a0f83 100644
--- a/templates/crate/details.html
+++ b/templates/crate/details.html
@@ -5,6 +5,17 @@
{{ macros::doc_title(name=details.name, version=details.version) }}
{%- endblock title -%}
+{%- block topbar -%}
+ {%- set metadata = details.metadata -%}
+ {%- set latest_version = "" -%}
+ {%- set latest_path = "" -%}
+ {%- set target = "" -%}
+ {%- set inner_path = details.metadata.target_name ~ "/index.html" -%}
+ {%- set is_latest_version = true -%}
+ {%- set is_prerelease = false -%}
+ {%- include "rustdoc/topbar.html" -%}
+{%- endblock topbar -%}
+
{%- block header -%}
{# Set the active tab to the `crate` tab #}
{{ navigation::package_navigation(metadata=details.metadata, active_tab="crate") }}
diff --git a/templates/crate/source.html b/templates/crate/source.html
index cf5c32bb0..4312e924d 100644
--- a/templates/crate/source.html
+++ b/templates/crate/source.html
@@ -5,6 +5,17 @@
{{ macros::doc_title(name=file_list.metadata.name, version=file_list.metadata.version) }}
{%- endblock title -%}
+{%- block topbar -%}
+ {%- set metadata = file_list.metadata -%}
+ {%- set latest_version = "" -%}
+ {%- set latest_path = "" -%}
+ {%- set target = "" -%}
+ {%- set inner_path = metadata.target_name ~ "/index.html" -%}
+ {%- set is_latest_version = true -%}
+ {%- set is_prerelease = false -%}
+ {%- include "rustdoc/topbar.html" -%}
+{%- endblock topbar -%}
+
{%- block header -%}
{# Set the active tab to the `source` tab #}
{{ navigation::package_navigation(metadata=file_list.metadata, active_tab="source") }}
diff --git a/templates/header/topbar.html b/templates/header/topbar.html
index 4092f5962..5b1d42f83 100644
--- a/templates/header/topbar.html
+++ b/templates/header/topbar.html
@@ -1,104 +1,2 @@
-{#
- This is the unchanging top bar that is on every single page.
- The only piece of context it can take is `search_query`, which should
- be a string and will populate the search field if it exists
-#}
-
+{%- include "header/topbar_begin.html" -%}
+{%- include "header/topbar_end.html" -%}
diff --git a/templates/header/topbar_begin.html b/templates/header/topbar_begin.html
new file mode 100644
index 000000000..b6b67303b
--- /dev/null
+++ b/templates/header/topbar_begin.html
@@ -0,0 +1,106 @@
+{#
+ This is the unchanging top bar that is on every single page.
+ The only piece of context it can take is `search_query`, which should
+ be a string and will populate the search field if it exists
+#}
+
+{%- import "macros.html" as macros -%}
+
+
diff --git a/templates/rustdoc/header.html b/templates/rustdoc/header.html
deleted file mode 100644
index bcbc49975..000000000
--- a/templates/rustdoc/header.html
+++ /dev/null
@@ -1,242 +0,0 @@
-{%- import "macros.html" as macros -%}
-
-{# The url of the current release, `/crate/:name/:version` #}
-{%- set crate_url = "/crate/" ~ krate.name ~ "/" ~ krate.version -%}
-
-
diff --git a/templates/rustdoc/topbar.html b/templates/rustdoc/topbar.html
new file mode 100644
index 000000000..f7c44dea1
--- /dev/null
+++ b/templates/rustdoc/topbar.html
@@ -0,0 +1,232 @@
+{%- import "macros.html" as macros -%}
+
+{# The url of the current release, `/crate/:name/:version` #}
+{%- set crate_url = "/crate/" ~ metadata.name ~ "/" ~ metadata.version -%}
+
+{%- include "header/topbar_begin.html" -%}
+
+
+
+{%- include "header/topbar_end.html" -%}
diff --git a/templates/style/_navbar.scss b/templates/style/_navbar.scss
index f103237b4..4aac81344 100644
--- a/templates/style/_navbar.scss
+++ b/templates/style/_navbar.scss
@@ -30,6 +30,10 @@ div.nav-container {
}
}
+ .pure-menu-right {
+ float: right;
+ }
+
form.landing-search-form-nav {
max-width: 1200px;
@@ -98,50 +102,74 @@ div.nav-container {
}
}
- div.rustdoc-navigation {
- span.title {
- display: none;
+ // use a .title span inside a menu to hide it on small screens
+ span.title {
+ display: none;
+ @media #{$media-sm} {
+ display: inline;
+ }
+ }
+
+ // Make menu item optional and disappear on small screens
+ .pure-menu-opt {
+ display: none;
+ @media #{$media-sm} {
+ display: inline-block;
+ }
+ }
+ // Make children of menu optional and disappear on small screens
+ .pure-menu-opt-children {
+ > .pure-menu-link::after {
+ display: none;
@media #{$media-sm} {
display: inline;
}
}
- div.package-details-menu {
- width: 350px;
+ &.pure-menu-allow-hover:hover > .pure-menu-children,
+ &.pure-menu-active > .pure-menu-children {
+ display: none;
+ @media #{$media-sm} {
+ display: block;
+ }
+ }
+ }
- p.description {
- font-family: $font-family-sans;
- font-size: 0.8em;
- color: #777; // color from pure
- padding: 0.5em 1em;
- margin: 0;
- }
+ div.package-details-menu {
+ width: 350px;
- ul.pure-menu-list {
- width: 100%;
- }
+ p.description {
+ font-family: $font-family-sans;
+ font-size: 0.8em;
+ color: #777; // color from pure
+ padding: 0.5em 1em;
+ margin: 0;
+ }
- div.right-border {
- border-right: 1px solid $color-border;
- }
+ ul.pure-menu-list {
+ width: 100%;
+ }
- a.pure-menu-link {
- word-wrap: normal;
- white-space: normal;
- }
+ div.right-border {
+ border-right: 1px solid $color-border;
+ }
+
+ a.pure-menu-link {
+ word-wrap: normal;
+ white-space: normal;
+ }
- div.sub-menu {
- max-height: 150px;
- overflow-y: auto;
+ div.sub-menu {
+ max-height: 150px;
+ overflow-y: auto;
- ul.pure-menu-list {
- border-top: none;
- }
+ ul.pure-menu-list {
+ border-top: none;
+ }
- li.pure-menu-item:last-child {
- border-bottom: none;
- }
+ li.pure-menu-item:last-child {
+ border-bottom: none;
}
}
}