Skip to content

Add version switcher #58603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 47 additions & 11 deletions src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@ book!(
RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook1;
);

fn generate_jump_version_js(p: &Path) -> String {
let content = fs::read(p).expect("file not found");
let s = String::from_utf8_lossy(&content);
let version_parts = crate::channel::CFG_RELEASE_NUM.split(".").collect::<Vec<_>>();
let mut versions = vec!["\"nightly\"".to_owned(),
"\"beta\"".to_owned(),
"\"stable\"".to_owned()];
let mut middle_version = i32::from_str_radix(version_parts[1], 10).expect("unknown number");

while middle_version >= 0 {
versions.push(format!("\"1.{}.0\"", middle_version));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be cool if we could also add bugfix releases in here, but that might be hard

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugfixes don't change API normally so I'm not sure it's really useful to add them in here.

middle_version -= 1;
}
s.replace("var VERSIONS = [];", &format!("var VERSIONS = [{}];", versions.join(",")))
}

fn generate_jump_version_css(p: &Path) -> String {
let content = fs::read(p).expect("file not found");
String::from_utf8(content).expect("invalid UTF8")
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
enum RustbookVersion {
MdBook1,
Expand Down Expand Up @@ -329,21 +350,23 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String
let favicon = builder.src.join("src/doc/favicon.inc");
let footer = builder.src.join("src/doc/footer.inc");
let version_info = out.join("version_info.html");
let jump_version_js = builder.src.join("src/doc/jump-version.js");
let jump_version_css = builder.src.join("src/doc/jump-version.css");

let mut cmd = builder.rustdoc_cmd(compiler.host);

let out = out.join("book");

cmd.arg("--html-after-content").arg(&footer)
.arg("--html-before-content").arg(&version_info)
.arg("--html-in-header").arg(&favicon)
.arg("--markdown-no-toc")
.arg("--markdown-playground-url")
.arg("https://play.rust-lang.org/")
.arg("-o").arg(&out)
.arg(&path)
.arg("--markdown-css")
.arg("../rust.css");
.arg("--html-before-content").arg(&version_info)
.arg("--html-in-header").arg(&favicon)
.arg("--raw-js-in-header").arg(&generate_jump_version_js(&jump_version_js))
.arg("--raw-css-in-header").arg(&generate_jump_version_css(&jump_version_css))
.arg("--markdown-no-toc")
.arg("--markdown-playground-url").arg("https://play.rust-lang.org/")
.arg("-o").arg(&out)
.arg("--markdown-css").arg("../rust.css")
.arg(&path);

builder.run(&mut cmd);
}
Expand Down Expand Up @@ -388,6 +411,8 @@ impl Step for Standalone {
let favicon = builder.src.join("src/doc/favicon.inc");
let footer = builder.src.join("src/doc/footer.inc");
let full_toc = builder.src.join("src/doc/full-toc.inc");
let jump_version_js = builder.src.join("src/doc/jump-version.js");
let jump_version_css = builder.src.join("src/doc/jump-version.css");
t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));

let version_input = builder.src.join("src/doc/version_info.html.template");
Expand Down Expand Up @@ -424,10 +449,13 @@ impl Step for Standalone {
cmd.arg("--html-after-content").arg(&footer)
.arg("--html-before-content").arg(&version_info)
.arg("--html-in-header").arg(&favicon)
.arg("--raw-js-in-header")
.arg(&generate_jump_version_js(&jump_version_js))
.arg("--raw-css-in-header")
.arg(&generate_jump_version_css(&jump_version_css))
.arg("--markdown-no-toc")
.arg("--index-page").arg(&builder.src.join("src/doc/index.md"))
.arg("--markdown-playground-url")
.arg("https://play.rust-lang.org/")
.arg("--markdown-playground-url").arg("https://play.rust-lang.org/")
.arg("-o").arg(&out)
.arg(&path);

Expand Down Expand Up @@ -506,6 +534,10 @@ impl Step for Std {
let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc");
compile::std_cargo(builder, &compiler, target, &mut cargo);


let jump_version_js = builder.src.join("src/doc/jump-version.js");
let jump_version_css = builder.src.join("src/doc/jump-version.css");

// Keep a whitelist so we do not build internal stdlib crates, these will be
// build by the rustc step later if enabled.
cargo.arg("-Z").arg("unstable-options")
Expand All @@ -518,6 +550,10 @@ impl Step for Std {
.arg("--markdown-css").arg("rust.css")
.arg("--markdown-no-toc")
.arg("--generate-redirect-pages")
.arg("--raw-js-in-header")
.arg(&generate_jump_version_js(&jump_version_js))
.arg("--raw-css-in-header")
.arg(&generate_jump_version_css(&jump_version_css))
.arg("--index-page").arg(&builder.src.join("src/doc/index.md"));

builder.run(&mut cargo);
Expand Down
11 changes: 11 additions & 0 deletions src/doc/jump-version.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#jump-version {
position: fixed;
right: 5px;
bottom: 5px;
border: 1px solid #ccc;
border-radius: 3px;
background-color: #eee;
color: #000;
padding: 4px;
font-size: 1.1em;
}
33 changes: 33 additions & 0 deletions src/doc/jump-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
(function(){
var VERSIONS = [];
if (window.location.protocol === "file:" || window.location.host !== "doc.rust-lang.org") {
return;
}
var version = window.location.pathname.split("/").filter(function(x) {
return x.length > 0;
})[0];
if (version === "std") {
version = "stable";
}
var s = document.createElement("select");
for (var i = 0; i < VERSIONS.length; ++i) {
var entry = document.createElement("option");
entry.innerText = VERSIONS[i];
entry.value = VERSIONS[i];
if (VERSIONS[i] === version) {
entry.selected = true;
}
s.append(entry);
}
s.id = "jump-version";
s.onchange = function() {
var parts = window.location.pathname.split("/").filter(function(x) {
return x.length > 0;
});
if (parts[0] !== "std") {
parts.shift();
}
window.location.pathname = this.value + "/" + parts.join("/");
};
document.body.appendChild(s);
}());
15 changes: 13 additions & 2 deletions src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ pub struct RenderOptions {
pub generate_search_filter: bool,
/// Option (disabled by default) to generate files used by RLS and some other tools.
pub generate_redirect_pages: bool,
/// Additional JS file (through "--raw-js-in-header" option).
pub additional_js: Option<String>,
/// Additional JS file (through "--raw-css-in-header" option).
pub additional_css: Option<String>,
}

impl Options {
Expand Down Expand Up @@ -360,14 +364,18 @@ impl Options {
}
}

let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();

let mut id_map = html::markdown::IdMap::new();
id_map.populate(html::render::initial_ids());
let external_html = match ExternalHtml::load(
&matches.opt_strs("html-in-header"),
&matches.opt_strs("html-before-content"),
&matches.opt_strs("html-after-content"),
&matches.opt_strs("markdown-before-content"),
&matches.opt_strs("markdown-after-content"), &diag, &mut id_map) {
&matches.opt_strs("markdown-after-content"),
&diag,
&mut id_map) {
Some(eh) => eh,
None => return Err(3),
};
Expand Down Expand Up @@ -428,7 +436,6 @@ impl Options {
let display_warnings = matches.opt_present("display-warnings");
let linker = matches.opt_str("linker").map(PathBuf::from);
let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
let enable_minification = !matches.opt_present("disable-minification");
let markdown_no_toc = matches.opt_present("markdown-no-toc");
let markdown_css = matches.opt_strs("markdown-css");
Expand All @@ -439,6 +446,8 @@ impl Options {
let generate_search_filter = !matches.opt_present("disable-per-crate-search");
let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
let generate_redirect_pages = matches.opt_present("generate-redirect-pages");
let additional_js = matches.opt_str("raw-js-in-header");
let additional_css = matches.opt_str("raw-css-in-header");

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

Expand Down Expand Up @@ -484,6 +493,8 @@ impl Options {
markdown_playground_url,
generate_search_filter,
generate_redirect_pages,
additional_js,
additional_css,
}
})
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/externalfiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ pub struct ExternalHtml {

impl ExternalHtml {
pub fn load(in_header: &[String], before_content: &[String], after_content: &[String],
md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler,
id_map: &mut IdMap)
md_before_content: &[String], md_after_content: &[String],
diag: &errors::Handler, id_map: &mut IdMap)
-> Option<ExternalHtml> {
let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
load_external_files(in_header, diag)
Expand Down
16 changes: 15 additions & 1 deletion src/librustdoc/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
css_file_extension: bool,
themes: &[PathBuf],
generate_search_filter: bool,
additional_js: bool,
additional_css: bool,
) -> io::Result<()> {
let static_root_path = page.static_root_path.unwrap_or(page.root_path);
write!(dst,
Expand All @@ -61,7 +63,7 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
{in_header}\
<style type=\"text/css\">\
#crate-search{{background-image:url(\"{static_root_path}down-arrow{suffix}.svg\");}}\
</style>\
</style>{additional_js}{additional_css}\
</head>\
<body class=\"rustdoc {css_class}\">\
<!--[if lte IE 8]>\
Expand Down Expand Up @@ -236,6 +238,18 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
} else {
""
},
additional_js = if additional_js {
format!("<script src=\"{}additional{}.js\"></script>",
static_root_path, page.resource_suffix)
} else {
String::new()
},
additional_css = if additional_css {
format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{}additional{}.css\">",
static_root_path, page.resource_suffix)
} else {
String::new()
},
)
}

Expand Down
38 changes: 33 additions & 5 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ struct SharedContext {
pub generate_search_filter: bool,
/// Option disabled by default to generate files used by RLS and some other tools.
pub generate_redirect_pages: bool,
/// Is additional JS content present.
pub additional_js: bool,
/// Is additional CSS content present.
pub additional_css: bool,
}

impl SharedContext {
Expand Down Expand Up @@ -519,6 +523,8 @@ pub fn run(mut krate: clean::Crate,
static_root_path,
generate_search_filter,
generate_redirect_pages,
additional_js,
additional_css,
..
} = options;

Expand Down Expand Up @@ -549,6 +555,8 @@ pub fn run(mut krate: clean::Crate,
static_root_path,
generate_search_filter,
generate_redirect_pages,
additional_js: additional_js.is_some(),
additional_css: additional_css.is_some(),
};

// If user passed in `--playground-url` arg, we fill in crate name here
Expand Down Expand Up @@ -885,6 +893,16 @@ themePicker.onblur = handleThemeButtonsBlur;
write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
static_files::SETTINGS_JS,
options.enable_minification)?;
if let Some(ref additional_js) = options.additional_js {
write_minify(cx.dst.join(&format!("additional{}.js", cx.shared.resource_suffix)),
additional_js,
options.enable_minification)?;
}
if let Some(ref additional_css) = options.additional_css {
write_minify(cx.dst.join(&format!("additional{}.css", cx.shared.resource_suffix)),
additional_css,
options.enable_minification)?;
}
if cx.shared.include_sources {
write_minify(cx.dst.join(&format!("source-script{}.js", cx.shared.resource_suffix)),
static_files::sidebar::SOURCE_SCRIPT,
Expand Down Expand Up @@ -1164,7 +1182,9 @@ themePicker.onblur = handleThemeButtonsBlur;
&page, &(""), &content,
cx.shared.css_file_extension.is_some(),
&cx.shared.themes,
cx.shared.generate_search_filter), &dst);
cx.shared.generate_search_filter,
options.additional_js.is_some(),
options.additional_css.is_some()), &dst);
try_err!(w.flush(), &dst);
}
}
Expand Down Expand Up @@ -1476,7 +1496,9 @@ impl<'a> SourceCollector<'a> {
&page, &(""), &Source(contents),
self.scx.css_file_extension.is_some(),
&self.scx.themes,
self.scx.generate_search_filter)?;
self.scx.generate_search_filter,
self.scx.additional_js,
self.scx.additional_css)?;
w.flush()?;
self.scx.local_sources.insert(p.clone(), href);
Ok(())
Expand Down Expand Up @@ -2084,7 +2106,9 @@ impl Context {
&page, &sidebar, &all,
self.shared.css_file_extension.is_some(),
&self.shared.themes,
self.shared.generate_search_filter),
self.shared.generate_search_filter,
self.shared.additional_js,
self.shared.additional_css),
&final_file);

// Generating settings page.
Expand All @@ -2102,7 +2126,9 @@ impl Context {
&page, &sidebar, &settings,
self.shared.css_file_extension.is_some(),
&themes,
self.shared.generate_search_filter),
self.shared.generate_search_filter,
self.shared.additional_js,
self.shared.additional_css),
&settings_file);

Ok(())
Expand Down Expand Up @@ -2164,7 +2190,9 @@ impl Context {
&Item{ cx: self, item: it },
self.shared.css_file_extension.is_some(),
&self.shared.themes,
self.shared.generate_search_filter)?;
self.shared.generate_search_filter,
self.shared.additional_js,
self.shared.additional_css)?;
} else {
let mut url = self.root_path();
if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) {
Expand Down
12 changes: 12 additions & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,18 @@ fn opts() -> Vec<RustcOptGroup> {
Markdown file or generated documentation",
"FILES")
}),
unstable("raw-js-in-header", |o| {
o.optopt("", "raw-js-in-header",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bikeshed warning: Since the included file eventually gets named additional.js/additional.css, i feel like these flags would be better named --additional-js/--additional-css.

I also feel like the flag description is a little misleading. Maybe something like:

(JS|CSS) file to include as a static file to be linked from generated documentation

(I feel like this feature would be much better served if it allowed multiple files, but that can be added in a separate PR. Since the flag will be unstable, we can edit it after it lands.)

"JS to include in the <head> section of a rendered Markdown file \
or generated documentation",
"text")
}),
unstable("raw-css-in-header", |o| {
o.optopt("", "raw-css-in-header",
"CSS to include in the <head> section of a rendered Markdown file \
or generated documentation",
"text")
}),
unstable("markdown-before-content", |o| {
o.optmulti("", "markdown-before-content",
"files to include inline between <body> and the content of a rendered \
Expand Down