Skip to content

Commit

Permalink
Rollup merge of rust-lang#57011 - QuietMisdreavus:static-root-path, r…
Browse files Browse the repository at this point in the history
…=GuillaumeGomez

rustdoc: add new CLI flag to load static files from a different location

This PR adds a new CLI flag to rustdoc, `--static-root-path`, which controls how rustdoc links pages to the CSS/JS/font static files bundled with the output. By default, these files are linked with a series of `../` which is calculated per-page to link it to the documentation root - i.e. a relative link to the directory given by `-o`. This is causing problems for docs.rs, because even though docs.rs has saved one copy of these files and is dispatching them dynamically, browsers have no way of knowing that these are the same files and can cache them. This can allow it to link these files as, for example, `/rustdoc.css` instead of `../../rustdoc.css`, creating a single location that the files are loaded from.

I made sure to only change links for the *static* files, those that don't change between crates. Files like the search index, aliases, the source files listing, etc, are still linked with relative links.

r? @GuillaumeGomez

cc @onur
  • Loading branch information
kennytm committed Dec 22, 2018
2 parents 5ba6a34 + 8dc8d7a commit 4446c65
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 22 deletions.
15 changes: 15 additions & 0 deletions src/doc/rustdoc/src/unstable-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,18 @@ Using `index-page` option enables `enable-index-page` option as well.
### `--enable-index-page`: generate a default index page for docs

This feature allows the generation of a default index-page which lists the generated crates.

### `--static-root-path`: control how static files are loaded in HTML output

Using this flag looks like this:

```bash
$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/'
```

This flag controls how rustdoc links to its static files on HTML pages. If you're hosting a lot of
crates' docs generated by the same version of rustdoc, you can use this flag to cache rustdoc's CSS,
JavaScript, and font files in a single location, rather than duplicating it once per "doc root"
(grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate
files like the search index will still load from the documentation root, but anything that gets
renamed with `--resource-suffix` will load from the given path.
5 changes: 5 additions & 0 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ pub struct RenderOptions {
/// A file to use as the index page at the root of the output directory. Overrides
/// `enable_index_page` to be true if set.
pub index_page: Option<PathBuf>,
/// An optional path to use as the location of static files. If not set, uses combinations of
/// `../` to reach the documentation root.
pub static_root_path: Option<String>,

// Options specific to reading standalone Markdown files

Expand Down Expand Up @@ -433,6 +436,7 @@ impl Options {
let markdown_playground_url = matches.opt_str("markdown-playground-url");
let crate_version = matches.opt_str("crate-version");
let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
let static_root_path = matches.opt_str("static-root-path");

let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);

Expand Down Expand Up @@ -471,6 +475,7 @@ impl Options {
enable_minification,
enable_index_page,
index_page,
static_root_path,
markdown_no_toc,
markdown_css,
markdown_playground_url,
Expand Down
49 changes: 33 additions & 16 deletions src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,20 @@ pub struct Page<'a> {
pub title: &'a str,
pub css_class: &'a str,
pub root_path: &'a str,
pub static_root_path: Option<&'a str>,
pub description: &'a str,
pub keywords: &'a str,
pub resource_suffix: &'a str,
pub extra_scripts: &'a [&'a str],
pub static_extra_scripts: &'a [&'a str],
}

pub fn render<T: fmt::Display, S: fmt::Display>(
dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T,
css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str])
css_file_extension: bool, themes: &[PathBuf])
-> io::Result<()>
{
let static_root_path = page.static_root_path.unwrap_or(page.root_path);
write!(dst,
"<!DOCTYPE html>\
<html lang=\"en\">\
Expand All @@ -46,20 +50,20 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
<meta name=\"description\" content=\"{description}\">\
<meta name=\"keywords\" content=\"{keywords}\">\
<title>{title}</title>\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}normalize{suffix}.css\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}rustdoc{suffix}.css\" \
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
id=\"mainThemeStyle\">\
{themes}\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}dark{suffix}.css\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}light{suffix}.css\" \
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}dark{suffix}.css\">\
<link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}light{suffix}.css\" \
id=\"themeStyle\">\
<script src=\"{root_path}storage{suffix}.js\"></script>\
<noscript><link rel=\"stylesheet\" href=\"{root_path}noscript{suffix}.css\"></noscript>\
<script src=\"{static_root_path}storage{suffix}.js\"></script>\
<noscript><link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\"></noscript>\
{css_extension}\
{favicon}\
{in_header}\
<style type=\"text/css\">\
#crate-search{{background-image:url(\"{root_path}down-arrow{suffix}.svg\");}}\
#crate-search{{background-image:url(\"{static_root_path}down-arrow{suffix}.svg\");}}\
</style>\
</head>\
<body class=\"rustdoc {css_class}\">\
Expand All @@ -77,11 +81,13 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
</nav>\
<div class=\"theme-picker\">\
<button id=\"theme-picker\" aria-label=\"Pick another theme!\">\
<img src=\"{root_path}brush{suffix}.svg\" width=\"18\" alt=\"Pick another theme!\">\
<img src=\"{static_root_path}brush{suffix}.svg\" \
width=\"18\" \
alt=\"Pick another theme!\">\
</button>\
<div id=\"theme-choices\"></div>\
</div>\
<script src=\"{root_path}theme{suffix}.js\"></script>\
<script src=\"{static_root_path}theme{suffix}.js\"></script>\
<nav class=\"sub\">\
<form class=\"search-form js-only\">\
<div class=\"search-container\">\
Expand All @@ -96,7 +102,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
type=\"search\">\
</div>\
<a id=\"settings-menu\" href=\"{root_path}settings.html\">\
<img src=\"{root_path}wheel{suffix}.svg\" width=\"18\" alt=\"Change settings\">\
<img src=\"{static_root_path}wheel{suffix}.svg\" \
width=\"18\" \
alt=\"Change settings\">\
</a>\
</div>\
</form>\
Expand Down Expand Up @@ -157,19 +165,23 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
window.currentCrate = \"{krate}\";\
</script>\
<script src=\"{root_path}aliases.js\"></script>\
<script src=\"{root_path}main{suffix}.js\"></script>\
<script src=\"{static_root_path}main{suffix}.js\"></script>\
{static_extra_scripts}\
{extra_scripts}\
<script defer src=\"{root_path}search-index.js\"></script>\
</body>\
</html>",
css_extension = if css_file_extension {
format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{root_path}theme{suffix}.css\">",
root_path = page.root_path,
format!("<link rel=\"stylesheet\" \
type=\"text/css\" \
href=\"{static_root_path}theme{suffix}.css\">",
static_root_path = static_root_path,
suffix=page.resource_suffix)
} else {
String::new()
},
content = *t,
static_root_path = static_root_path,
root_path = page.root_path,
css_class = page.css_class,
logo = if layout.logo.is_empty() {
Expand Down Expand Up @@ -197,12 +209,17 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
.filter_map(|t| t.file_stem())
.filter_map(|t| t.to_str())
.map(|t| format!(r#"<link rel="stylesheet" type="text/css" href="{}{}{}.css">"#,
page.root_path,
static_root_path,
t,
page.resource_suffix))
.collect::<String>(),
suffix=page.resource_suffix,
extra_scripts=extra_scripts.iter().map(|e| {
static_extra_scripts=page.static_extra_scripts.iter().map(|e| {
format!("<script src=\"{static_root_path}{extra_script}.js\"></script>",
static_root_path=static_root_path,
extra_script=e)
}).collect::<String>(),
extra_scripts=page.extra_scripts.iter().map(|e| {
format!("<script src=\"{root_path}{extra_script}.js\"></script>",
root_path=page.root_path,
extra_script=e)
Expand Down
28 changes: 22 additions & 6 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ struct SharedContext {
/// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes
/// "light-v2.css").
pub resource_suffix: String,
/// Optional path string to be used to load static files on output pages. If not set, uses
/// combinations of `../` to reach the documentation root.
pub static_root_path: Option<String>,
}

impl SharedContext {
Expand Down Expand Up @@ -506,6 +509,7 @@ pub fn run(mut krate: clean::Crate,
extension_css,
extern_html_root_urls,
resource_suffix,
static_root_path,
..
} = options;

Expand Down Expand Up @@ -533,6 +537,7 @@ pub fn run(mut krate: clean::Crate,
sort_modules_alphabetically,
themes,
resource_suffix,
static_root_path,
};

// If user passed in `--playground-url` arg, we fill in crate name here
Expand Down Expand Up @@ -1080,9 +1085,12 @@ themePicker.onblur = handleThemeButtonsBlur;
title: "Index of crates",
css_class: "mod",
root_path: "./",
static_root_path: cx.shared.static_root_path.deref(),
description: "List of crates",
keywords: BASIC_KEYWORDS,
resource_suffix: &cx.shared.resource_suffix,
extra_scripts: &[],
static_extra_scripts: &[],
};
krates.push(krate.name.clone());
krates.sort();
Expand All @@ -1101,7 +1109,7 @@ themePicker.onblur = handleThemeButtonsBlur;
try_err!(layout::render(&mut w, &cx.shared.layout,
&page, &(""), &content,
cx.shared.css_file_extension.is_some(),
&cx.shared.themes, &[]), &dst);
&cx.shared.themes), &dst);
try_err!(w.flush(), &dst);
}
}
Expand Down Expand Up @@ -1366,15 +1374,17 @@ impl<'a> SourceCollector<'a> {
title: &title,
css_class: "source",
root_path: &root_path,
static_root_path: self.scx.static_root_path.deref(),
description: &desc,
keywords: BASIC_KEYWORDS,
resource_suffix: &self.scx.resource_suffix,
extra_scripts: &["source-files"],
static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
};
layout::render(&mut w, &self.scx.layout,
&page, &(""), &Source(contents),
self.scx.css_file_extension.is_some(),
&self.scx.themes, &["source-files",
&format!("source-script{}", page.resource_suffix)])?;
&self.scx.themes)?;
w.flush()?;
self.scx.local_sources.insert(p.clone(), href);
Ok(())
Expand Down Expand Up @@ -1956,9 +1966,12 @@ impl Context {
title: "List of all items in this crate",
css_class: "mod",
root_path: "../",
static_root_path: self.shared.static_root_path.deref(),
description: "List of all items in this crate",
keywords: BASIC_KEYWORDS,
resource_suffix: &self.shared.resource_suffix,
extra_scripts: &[],
static_extra_scripts: &[],
};
let sidebar = if let Some(ref version) = cache().crate_version {
format!("<p class='location'>Crate {}</p>\
Expand All @@ -1973,7 +1986,7 @@ impl Context {
try_err!(layout::render(&mut w, &self.shared.layout,
&page, &sidebar, &all,
self.shared.css_file_extension.is_some(),
&self.shared.themes, &[]),
&self.shared.themes),
&final_file);

// Generating settings page.
Expand All @@ -1993,7 +2006,7 @@ impl Context {
try_err!(layout::render(&mut w, &layout,
&page, &sidebar, &settings,
self.shared.css_file_extension.is_some(),
&themes, &[]),
&themes),
&settings_file);

Ok(())
Expand Down Expand Up @@ -2035,10 +2048,13 @@ impl Context {
let page = layout::Page {
css_class: tyname,
root_path: &self.root_path(),
static_root_path: self.shared.static_root_path.deref(),
title: &title,
description: &desc,
keywords: &keywords,
resource_suffix: &self.shared.resource_suffix,
extra_scripts: &[],
static_extra_scripts: &[],
};

{
Expand All @@ -2051,7 +2067,7 @@ impl Context {
&Sidebar{ cx: self, item: it },
&Item{ cx: self, item: it },
self.shared.css_file_extension.is_some(),
&self.shared.themes, &[])?;
&self.shared.themes)?;
} else {
let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
Expand Down
8 changes: 8 additions & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#![feature(crate_visibility_modifier)]
#![feature(const_fn)]
#![feature(drain_filter)]
#![feature(inner_deref)]

#![recursion_limit="256"]

Expand Down Expand Up @@ -338,6 +339,13 @@ fn opts() -> Vec<RustcOptGroup> {
"enable-index-page",
"To enable generation of the index page")
}),
unstable("static-root-path", |o| {
o.optopt("",
"static-root-path",
"Path string to force loading static files from in output pages. \
If not set, uses combinations of '../' to reach the documentation root.",
"PATH")
}),
]
}

Expand Down
24 changes: 24 additions & 0 deletions src/test/rustdoc/static-root-path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// compile-flags:-Z unstable-options --static-root-path /cache/

// @has static_root_path/struct.SomeStruct.html
// @matches - '"/cache/main\.js"'
// @!matches - '"\.\./main\.js"'
// @matches - '"\.\./search-index\.js"'
// @!matches - '"/cache/search-index\.js"'
pub struct SomeStruct;

// @has src/static_root_path/static-root-path.rs.html
// @matches - '"/cache/source-script\.js"'
// @!matches - '"\.\./\.\./source-script\.js"'
// @matches - '"\.\./\.\./source-files.js"'
// @!matches - '"/cache/source-files\.js"'

0 comments on commit 4446c65

Please sign in to comment.