From cb834c7effd86b6c00fdf789d5184c7cb273931c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 21 Aug 2020 10:09:35 -0400 Subject: [PATCH] Revert "Vendor FontAwesome and Pure-CSS" --- .gitignore | 1 - README.md | 15 - build.rs | 7 +- dockerfiles/Dockerfile | 2 - src/storage/mod.rs | 8 +- src/web/crate_details.rs | 2 +- src/web/metrics.rs | 6 +- src/web/mod.rs | 53 +- src/web/routes.rs | 6 +- src/web/rustdoc.rs | 2 +- src/web/statics.rs | 252 -- templates/base.html | 13 +- templates/rustdoc/body.html | 4 +- templates/rustdoc/head.html | 7 +- templates/style/base.scss | 3 +- vendor/fontawesome/LICENSE.txt | 34 - vendor/fontawesome/scss/_animated.scss | 20 - vendor/fontawesome/scss/_bordered-pulled.scss | 20 - vendor/fontawesome/scss/_core.scss | 21 - vendor/fontawesome/scss/_fixed-width.scss | 6 - vendor/fontawesome/scss/_icons.scss | 1451 --------- vendor/fontawesome/scss/_larger.scss | 23 - vendor/fontawesome/scss/_list.scss | 18 - vendor/fontawesome/scss/_mixins.scss | 56 - vendor/fontawesome/scss/_rotated-flipped.scss | 24 - vendor/fontawesome/scss/_screen-reader.scss | 5 - vendor/fontawesome/scss/_shims.scss | 2631 ----------------- vendor/fontawesome/scss/_stacked.scss | 31 - vendor/fontawesome/scss/_variables.scss | 1468 --------- vendor/fontawesome/scss/brands.scss | 23 - vendor/fontawesome/scss/fontawesome.scss | 16 - vendor/fontawesome/scss/regular.scss | 23 - vendor/fontawesome/scss/solid.scss | 24 - vendor/fontawesome/scss/v4-shims.scss | 6 - vendor/fontawesome/webfonts/fa-brands-400.eot | Bin 134622 -> 0 bytes vendor/fontawesome/webfonts/fa-brands-400.svg | 461 --- vendor/fontawesome/webfonts/fa-brands-400.ttf | Bin 134316 -> 0 bytes .../fontawesome/webfonts/fa-brands-400.woff | Bin 90672 -> 0 bytes .../fontawesome/webfonts/fa-brands-400.woff2 | Bin 77400 -> 0 bytes .../fontawesome/webfonts/fa-regular-400.eot | Bin 34350 -> 0 bytes .../fontawesome/webfonts/fa-regular-400.svg | 164 - .../fontawesome/webfonts/fa-regular-400.ttf | Bin 34052 -> 0 bytes .../fontawesome/webfonts/fa-regular-400.woff | Bin 16780 -> 0 bytes .../fontawesome/webfonts/fa-regular-400.woff2 | Bin 13600 -> 0 bytes vendor/fontawesome/webfonts/fa-solid-900.eot | Bin 204266 -> 0 bytes vendor/fontawesome/webfonts/fa-solid-900.svg | 1012 ------- vendor/fontawesome/webfonts/fa-solid-900.ttf | Bin 203980 -> 0 bytes vendor/fontawesome/webfonts/fa-solid-900.woff | Bin 104004 -> 0 bytes .../fontawesome/webfonts/fa-solid-900.woff2 | Bin 80148 -> 0 bytes vendor/pure-css/LICENSE | 29 - vendor/pure-css/css/grids-responsive-min.css | 7 - vendor/pure-css/css/pure-min.css | 11 - 52 files changed, 86 insertions(+), 7879 deletions(-) delete mode 100644 src/web/statics.rs delete mode 100644 vendor/fontawesome/LICENSE.txt delete mode 100644 vendor/fontawesome/scss/_animated.scss delete mode 100644 vendor/fontawesome/scss/_bordered-pulled.scss delete mode 100644 vendor/fontawesome/scss/_core.scss delete mode 100644 vendor/fontawesome/scss/_fixed-width.scss delete mode 100644 vendor/fontawesome/scss/_icons.scss delete mode 100644 vendor/fontawesome/scss/_larger.scss delete mode 100644 vendor/fontawesome/scss/_list.scss delete mode 100644 vendor/fontawesome/scss/_mixins.scss delete mode 100644 vendor/fontawesome/scss/_rotated-flipped.scss delete mode 100644 vendor/fontawesome/scss/_screen-reader.scss delete mode 100644 vendor/fontawesome/scss/_shims.scss delete mode 100644 vendor/fontawesome/scss/_stacked.scss delete mode 100644 vendor/fontawesome/scss/_variables.scss delete mode 100644 vendor/fontawesome/scss/brands.scss delete mode 100644 vendor/fontawesome/scss/fontawesome.scss delete mode 100644 vendor/fontawesome/scss/regular.scss delete mode 100644 vendor/fontawesome/scss/solid.scss delete mode 100644 vendor/fontawesome/scss/v4-shims.scss delete mode 100644 vendor/fontawesome/webfonts/fa-brands-400.eot delete mode 100644 vendor/fontawesome/webfonts/fa-brands-400.svg delete mode 100644 vendor/fontawesome/webfonts/fa-brands-400.ttf delete mode 100644 vendor/fontawesome/webfonts/fa-brands-400.woff delete mode 100644 vendor/fontawesome/webfonts/fa-brands-400.woff2 delete mode 100644 vendor/fontawesome/webfonts/fa-regular-400.eot delete mode 100644 vendor/fontawesome/webfonts/fa-regular-400.svg delete mode 100644 vendor/fontawesome/webfonts/fa-regular-400.ttf delete mode 100644 vendor/fontawesome/webfonts/fa-regular-400.woff delete mode 100644 vendor/fontawesome/webfonts/fa-regular-400.woff2 delete mode 100644 vendor/fontawesome/webfonts/fa-solid-900.eot delete mode 100644 vendor/fontawesome/webfonts/fa-solid-900.svg delete mode 100644 vendor/fontawesome/webfonts/fa-solid-900.ttf delete mode 100644 vendor/fontawesome/webfonts/fa-solid-900.woff delete mode 100644 vendor/fontawesome/webfonts/fa-solid-900.woff2 delete mode 100644 vendor/pure-css/LICENSE delete mode 100644 vendor/pure-css/css/grids-responsive-min.css delete mode 100644 vendor/pure-css/css/pure-min.css diff --git a/.gitignore b/.gitignore index f610a3252..d7823cbaf 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ target *.css *.css.map -!vendor/**/*.css .sass-cache .vagrant .rustwide diff --git a/README.md b/README.md index 3f399161b..9f257d5f1 100644 --- a/README.md +++ b/README.md @@ -210,21 +210,6 @@ cargo run -- daemon --registry-watcher=disabled cargo run -- queue add ``` -### Updating vendored sources - -The instructions & links for updating Font Awesome can be found [on their website](https://fontawesome.com/how-to-use/on-the-web/using-with/sass). Similarly, Pure-CSS also [explains on theirs](https://purecss.io/start/). - -When updating Font Awesome, make sure to change `$fa-font-path` in `scss/_variables.scss` (it should be at the top of the file) to `../-/static`. This will point font awesome at the correct path from which to request font and icon resources. - - ### Contact Docs.rs is run and maintained by the [docs.rs team](https://www.rust-lang.org/governance/teams/dev-tools#docs-rs). diff --git a/build.rs b/build.rs index 0a9847a24..9b68773a9 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,6 @@ fn main() { println!("cargo:rerun-if-changed=templates/style/_navbar.scss"); println!("cargo:rerun-if-changed=templates/menu.js"); println!("cargo:rerun-if-changed=templates/index.js"); - println!("cargo:rerun-if-changed=vendor/"); // TODO: are these right? println!("cargo:rerun-if-changed=.git/HEAD"); println!("cargo:rerun-if-changed=.git/index"); @@ -64,11 +63,7 @@ fn compile_sass() -> Result<(), Box> { let mut context = Context::new_file(format!("{}/base.scss", STYLE_DIR))?; context.set_options(Options { output_style: OutputStyle::Compressed, - include_paths: vec![ - STYLE_DIR.to_owned(), - concat!(env!("CARGO_MANIFEST_DIR"), "/vendor/fontawesome/scss").to_owned(), - concat!(env!("CARGO_MANIFEST_DIR"), "/vendor/pure-css/css").to_owned(), - ], + include_paths: vec![STYLE_DIR.to_owned()], ..Default::default() }); diff --git a/dockerfiles/Dockerfile b/dockerfiles/Dockerfile index d6dd4dc22..f72e59d1c 100644 --- a/dockerfiles/Dockerfile +++ b/dockerfiles/Dockerfile @@ -50,7 +50,6 @@ RUN find src -name "*.rs" -exec touch {} \; COPY templates/style templates/style COPY templates/index.js templates/ COPY templates/menu.js templates/ -COPY vendor vendor/ RUN cargo build --release @@ -76,7 +75,6 @@ COPY --from=build /build/target/release/cratesfyi /usr/local/bin COPY static /opt/docsrs/prefix/public_html COPY templates /opt/docsrs/templates COPY dockerfiles/entrypoint.sh /opt/docsrs/ -COPY vendor vendor/ WORKDIR /opt/docsrs ENTRYPOINT ["/opt/docsrs/entrypoint.sh"] diff --git a/src/storage/mod.rs b/src/storage/mod.rs index 61a4a2e3f..8e9939ec6 100644 --- a/src/storage/mod.rs +++ b/src/storage/mod.rs @@ -190,7 +190,7 @@ impl Storage { #[cfg(test)] pub(crate) fn store_blobs(&self, blobs: Vec) -> Result<(), Error> { - self.store_inner(blobs.into_iter().map(Ok)) + self.store_inner(blobs.into_iter().map(|blob| Ok(blob))) } fn store_inner( @@ -276,7 +276,7 @@ mod test { crate::test::init_logger(); let files = get_file_list(env::current_dir().unwrap()); assert!(files.is_ok()); - assert!(!files.unwrap().is_empty()); + assert!(files.unwrap().len() > 0); let files = get_file_list(env::current_dir().unwrap().join("Cargo.toml")).unwrap(); assert_eq!(files[0], std::path::Path::new("Cargo.toml")); @@ -375,7 +375,7 @@ mod backend_tests { compression: None, }; - storage.store_blobs(vec![small_blob.clone(), big_blob])?; + storage.store_blobs(vec![small_blob.clone(), big_blob.clone()])?; let blob = storage.get("small-blob.bin", MAX_SIZE)?; assert_eq!(blob.content.len(), small_blob.content.len()); @@ -480,7 +480,7 @@ mod backend_tests { mime: "text/rust".into(), content, path: format!("{}.rs", i), - date_updated: now, + date_updated: now.clone(), compression: None, } }) diff --git a/src/web/crate_details.rs b/src/web/crate_details.rs index d55edf9d8..0e7de9ce2 100644 --- a/src/web/crate_details.rs +++ b/src/web/crate_details.rs @@ -696,7 +696,7 @@ mod tests { .create()?; let details = CrateDetails::new(&mut db.conn(), "foo", "0.0.1").unwrap(); - let mut owners = details.owners; + let mut owners = details.owners.clone(); owners.sort(); assert_eq!( owners, diff --git a/src/web/metrics.rs b/src/web/metrics.rs index 969d854e8..44c26358d 100644 --- a/src/web/metrics.rs +++ b/src/web/metrics.rs @@ -117,8 +117,8 @@ mod tests { ("/", "/"), ("/crate/hexponent/0.2.0", "/crate/:name/:version"), ("/crate/rcc/0.0.0", "/crate/:name/:version"), - ("/-/static/index.js", "static resource"), - ("/-/static/menu.js", "static resource"), + ("/index.js", "static resource"), + ("/menu.js", "static resource"), ("/opensearch.xml", "static resource"), ("/releases", "/releases"), ("/releases/feed", "static resource"), @@ -131,7 +131,7 @@ mod tests { ("/releases/recent/1", "/releases/recent/:page"), ("/robots.txt", "static resource"), ("/sitemap.xml", "static resource"), - ("/-/static/style.css", "static resource"), + ("/style.css", "static resource"), ]; wrapper(|env| { diff --git a/src/web/mod.rs b/src/web/mod.rs index eeaa8edb0..032df84be 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -87,7 +87,6 @@ mod routes; mod rustdoc; mod sitemap; mod source; -mod statics; use crate::{impl_webpage, Context}; use chrono::{DateTime, Utc}; @@ -111,6 +110,9 @@ use std::{borrow::Cow, env, fmt, net::SocketAddr, path::PathBuf, sync::Arc, time /// Duration of static files for staticfile and DatabaseFileHandler (in seconds) const STATIC_FILE_CACHE_DURATION: u64 = 60 * 60 * 24 * 30 * 12; // 12 months +const STYLE_CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/style.css")); +const MENU_JS: &str = include_str!(concat!(env!("OUT_DIR"), "/menu.js")); +const INDEX_JS: &str = include_str!(concat!(env!("OUT_DIR"), "/index.js")); const OPENSEARCH_XML: &[u8] = include_bytes!("opensearch.xml"); const DEFAULT_BIND: &str = "0.0.0.0:3000"; @@ -493,6 +495,35 @@ fn redirect_base(req: &Request) -> String { } } +fn style_css_handler(_: &mut Request) -> IronResult { + let mut response = Response::with((status::Ok, STYLE_CSS)); + let cache = vec![ + CacheDirective::Public, + CacheDirective::MaxAge(STATIC_FILE_CACHE_DURATION as u32), + ]; + + response + .headers + .set(ContentType("text/css".parse().unwrap())); + response.headers.set(CacheControl(cache)); + + Ok(response) +} + +fn load_js(file_path_str: &'static str) -> IronResult { + let mut response = Response::with((status::Ok, file_path_str)); + let cache = vec![ + CacheDirective::Public, + CacheDirective::MaxAge(STATIC_FILE_CACHE_DURATION as u32), + ]; + response + .headers + .set(ContentType("application/javascript".parse().unwrap())); + response.headers.set(CacheControl(cache)); + + Ok(response) +} + fn opensearch_xml_handler(_: &mut Request) -> IronResult { let mut response = Response::with((status::Ok, OPENSEARCH_XML)); let cache = vec![ @@ -508,6 +539,26 @@ fn opensearch_xml_handler(_: &mut Request) -> IronResult { Ok(response) } +fn ico_handler(req: &mut Request) -> IronResult { + if let Some(&"favicon.ico") = req.url.path().last() { + // if we're looking for exactly "favicon.ico", we need to defer to the handler that loads + // from `public_html`, so return a 404 here to make the main handler carry on + Err(IronError::new( + error::Nope::ResourceNotFound, + status::NotFound, + )) + } else { + // if we're looking for something like "favicon-20190317-1.35.0-nightly-c82834e2b.ico", + // redirect to the plain one so that the above branch can trigger with the correct filename + let url = ctry!( + req, + Url::parse(&format!("{}/favicon.ico", redirect_base(req))), + ); + + Ok(redirect(url)) + } +} + /// MetaData used in header #[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub(crate) struct MetaData { diff --git a/src/web/routes.rs b/src/web/routes.rs index bd874abb9..a7a8d5d21 100644 --- a/src/web/routes.rs +++ b/src/web/routes.rs @@ -1,5 +1,7 @@ use super::metrics::RequestRecorder; +use crate::web::{INDEX_JS, MENU_JS}; use iron::middleware::Handler; +use iron::Request; use router::Router; use std::collections::HashSet; @@ -10,10 +12,12 @@ pub(super) const DOC_RUST_LANG_ORG_REDIRECTS: &[&str] = pub(super) fn build_routes() -> Routes { let mut routes = Routes::new(); + routes.static_resource("/style.css", super::style_css_handler); + routes.static_resource("/index.js", |_: &mut Request| super::load_js(INDEX_JS)); + routes.static_resource("/menu.js", |_: &mut Request| super::load_js(MENU_JS)); routes.static_resource("/robots.txt", super::sitemap::robots_txt_handler); routes.static_resource("/sitemap.xml", super::sitemap::sitemap_handler); routes.static_resource("/opensearch.xml", super::opensearch_xml_handler); - routes.static_resource("/-/static/:file", super::statics::static_handler); routes.internal_page("/", super::releases::home_page); diff --git a/src/web/rustdoc.rs b/src/web/rustdoc.rs index 3b205eef5..a2410b064 100644 --- a/src/web/rustdoc.rs +++ b/src/web/rustdoc.rs @@ -125,7 +125,7 @@ pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult { { // route .ico files into their dedicated handler so that docs.rs's favicon is always // displayed - return super::statics::ico_handler(req); + return super::ico_handler(req); } let router = extension!(req, Router); diff --git a/src/web/statics.rs b/src/web/statics.rs deleted file mode 100644 index 022a99a79..000000000 --- a/src/web/statics.rs +++ /dev/null @@ -1,252 +0,0 @@ -use super::{error::Nope, redirect, redirect_base, STATIC_FILE_CACHE_DURATION}; -use chrono::Utc; -use iron::{ - headers::CacheDirective, - headers::{CacheControl, ContentLength, ContentType, LastModified}, - status::Status, - IronError, IronResult, Request, Response, Url, -}; -use mime_guess::MimeGuess; -use router::Router; -use std::{ffi::OsStr, fs, path::Path}; - -const STYLE_CSS: &str = include_str!(concat!(env!("OUT_DIR"), "/style.css")); -const MENU_JS: &str = include_str!(concat!(env!("OUT_DIR"), "/menu.js")); -const INDEX_JS: &str = include_str!(concat!(env!("OUT_DIR"), "/index.js")); -const STATIC_SEARCH_PATHS: &[&str] = &["vendor/fontawesome/webfonts", "vendor/pure-css/css"]; - -pub(crate) fn static_handler(req: &mut Request) -> IronResult { - let router = extension!(req, Router); - let file = cexpect!(req, router.find("file")); - - match file { - "style.css" => serve_resource(STYLE_CSS, ContentType("text/css".parse().unwrap())), - "index.js" => serve_resource( - INDEX_JS, - ContentType("application/javascript".parse().unwrap()), - ), - "menu.js" => serve_resource( - MENU_JS, - ContentType("application/javascript".parse().unwrap()), - ), - - file => serve_file(req, file), - } -} - -fn serve_file(req: &Request, file: &str) -> IronResult { - // Filter out files that attempt to traverse directories - if file.contains("..") || file.contains('/') || file.contains('\\') { - return Err(IronError::new(Nope::ResourceNotFound, Status::NotFound)); - } - - // Find the first path that actually exists - let path = STATIC_SEARCH_PATHS - .iter() - .map(|p| Path::new(p).join(file)) - .find(|p| p.exists()) - .ok_or_else(|| IronError::new(Nope::ResourceNotFound, Status::NotFound))?; - let contents = ctry!(req, fs::read(&path)); - - // If we can detect the file's mime type, set it - // MimeGuess misses a lot of the file types we need, so there's a small wrapper - // around it - let content_type = path - .extension() - .and_then(OsStr::to_str) - .and_then(|ext| match ext { - "eot" => Some(ContentType( - "application/vnd.ms-fontobject".parse().unwrap(), - )), - "woff2" => Some(ContentType("application/font-woff2".parse().unwrap())), - "ttf" => Some(ContentType("application/x-font-ttf".parse().unwrap())), - - _ => MimeGuess::from_path(&path) - .first() - .map(|mime| ContentType(mime.as_ref().parse().unwrap())), - }); - - serve_resource(contents, content_type) -} - -fn serve_resource(resource: R, content_type: C) -> IronResult -where - R: AsRef<[u8]>, - C: Into>, -{ - let mut response = Response::with((Status::Ok, resource.as_ref())); - - let cache = vec![ - CacheDirective::Public, - CacheDirective::MaxAge(STATIC_FILE_CACHE_DURATION as u32), - ]; - response.headers.set(CacheControl(cache)); - - response - .headers - .set(ContentLength(resource.as_ref().len() as u64)); - response.headers.set(LastModified( - Utc::now() - .format("%a, %d %b %Y %T %Z") - .to_string() - .parse() - .unwrap(), - )); - - if let Some(content_type) = content_type.into() { - response.headers.set(content_type); - } - - Ok(response) -} - -pub(super) fn ico_handler(req: &mut Request) -> IronResult { - if let Some(&"favicon.ico") = req.url.path().last() { - // if we're looking for exactly "favicon.ico", we need to defer to the handler that loads - // from `public_html`, so return a 404 here to make the main handler carry on - Err(IronError::new(Nope::ResourceNotFound, Status::NotFound)) - } else { - // if we're looking for something like "favicon-20190317-1.35.0-nightly-c82834e2b.ico", - // redirect to the plain one so that the above branch can trigger with the correct filename - let url = ctry!( - req, - Url::parse(&format!("{}/favicon.ico", redirect_base(req))), - ); - - Ok(redirect(url)) - } -} - -#[cfg(test)] -mod tests { - use super::{INDEX_JS, MENU_JS, STATIC_SEARCH_PATHS, STYLE_CSS}; - use crate::test::wrapper; - use std::fs; - - #[test] - fn style_css() { - wrapper(|env| { - let web = env.frontend(); - - let resp = web.get("/-/static/style.css").send()?; - assert!(resp.status().is_success()); - assert_eq!( - resp.headers().get("Content-Type"), - Some(&"text/css".parse().unwrap()), - ); - assert_eq!(resp.content_length().unwrap(), STYLE_CSS.len() as u64); - assert_eq!(resp.text()?, STYLE_CSS); - - Ok(()) - }); - } - - #[test] - fn index_js() { - wrapper(|env| { - let web = env.frontend(); - - let resp = web.get("/-/static/index.js").send()?; - assert!(resp.status().is_success()); - assert_eq!( - resp.headers().get("Content-Type"), - Some(&"application/javascript".parse().unwrap()), - ); - assert_eq!(resp.content_length().unwrap(), INDEX_JS.len() as u64); - assert_eq!(resp.text()?, INDEX_JS); - - Ok(()) - }); - } - - #[test] - fn menu_js() { - wrapper(|env| { - let web = env.frontend(); - - let resp = web.get("/-/static/menu.js").send()?; - assert!(resp.status().is_success()); - assert_eq!( - resp.headers().get("Content-Type"), - Some(&"application/javascript".parse().unwrap()), - ); - assert_eq!(resp.content_length().unwrap(), MENU_JS.len() as u64); - assert_eq!(resp.text()?, MENU_JS); - - Ok(()) - }); - } - - #[test] - fn static_files() { - wrapper(|env| { - let web = env.frontend(); - - for path in STATIC_SEARCH_PATHS { - for (file, path) in fs::read_dir(path)? - .map(|e| e.unwrap()) - .map(|e| (e.file_name(), e.path())) - { - let url = format!("/-/static/{}", file.to_str().unwrap()); - let resp = web.get(&url).send()?; - - assert!(resp.status().is_success(), "failed to fetch {:?}", url); - assert_eq!( - resp.bytes()?, - fs::read(&path).unwrap(), - "failed to fetch {:?}", - url, - ); - } - } - - Ok(()) - }); - } - - #[test] - fn static_file_that_doesnt_exist() { - wrapper(|env| { - let web = env.frontend(); - assert_eq!( - web.get("/-/static/whoop-de-do.png") - .send()? - .status() - .as_u16(), - 404, - ); - - Ok(()) - }); - } - - #[test] - fn static_mime_types() { - wrapper(|env| { - let web = env.frontend(); - - let files = &[ - ("pure-min.css", "text/css"), - ("fa-brands-400.eot", "application/vnd.ms-fontobject"), - ("fa-brands-400.svg", "image/svg+xml"), - ("fa-brands-400.ttf", "application/x-font-ttf"), - ("fa-brands-400.woff", "application/font-woff"), - ("fa-brands-400.woff2", "application/font-woff2"), - ]; - - for (file, mime) in files { - let url = format!("/-/static/{}", file); - let resp = web.get(&url).send()?; - - assert_eq!( - resp.headers().get("Content-Type"), - Some(&mime.parse().unwrap()), - "{:?} has an incorrect content type", - url, - ); - } - - Ok(()) - }); - } -} diff --git a/templates/base.html b/templates/base.html index e313b3a4e..1bf090f9d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -9,11 +9,18 @@ {%- block meta -%}{%- endblock meta -%} + {# External styles #} + + + + {# Docs.rs styles #} - + {%- block css -%}{%- endblock css -%} @@ -30,8 +37,8 @@ {%- block body -%}{%- endblock body -%} - - + + {%- block javascript -%}{%- endblock javascript -%} diff --git a/templates/rustdoc/body.html b/templates/rustdoc/body.html index 4cfd2c4f4..f9a2beb8f 100644 --- a/templates/rustdoc/body.html +++ b/templates/rustdoc/body.html @@ -1,5 +1,5 @@ - - + +