Skip to content

Commit e53a5ff

Browse files
committed
Auto merge of #54543 - GuillaumeGomez:top-level-index, r=QuietMisdreavus
Add index page argument @Mark-Simulacrum: I might need some help from you: in bootstrap, I want to add an argument (a new flag added into `rustdoc`) in order to generate the current index directly when `rustdoc` is documenting the `std` lib. However, my change in `bootstrap` didn't do it and I assume it must be moved inside the `Std` struct. But there, I don't see how to pass it to `rustdoc` through `cargo`. Did I miss anything? r? @QuietMisdreavus
2 parents 87a3c1e + 2b64605 commit e53a5ff

File tree

7 files changed

+179
-54
lines changed

7 files changed

+179
-54
lines changed

src/bootstrap/builder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ impl<'a> Builder<'a> {
713713
"build" => self.cargo_out(compiler, mode, target),
714714

715715
// This is the intended out directory for crate documentation.
716-
"doc" => self.crate_doc_out(target),
716+
"doc" | "rustdoc" => self.crate_doc_out(target),
717717

718718
_ => self.stage_out(compiler, mode),
719719
};
@@ -742,7 +742,7 @@ impl<'a> Builder<'a> {
742742
_ => compile::librustc_stamp(self, cmp, target),
743743
};
744744

745-
if cmd == "doc" {
745+
if cmd == "doc" || cmd == "rustdoc" {
746746
if mode == Mode::Rustc || mode == Mode::ToolRustc || mode == Mode::Codegen {
747747
// This is the intended out directory for compiler documentation.
748748
my_out = self.compiler_doc_out(target);
@@ -882,7 +882,7 @@ impl<'a> Builder<'a> {
882882
.env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
883883
.env(
884884
"RUSTDOC_REAL",
885-
if cmd == "doc" || (cmd == "test" && want_rustdoc) {
885+
if cmd == "doc" || cmd == "rustdoc" || (cmd == "test" && want_rustdoc) {
886886
self.rustdoc(compiler.host)
887887
} else {
888888
PathBuf::from("/path/to/nowhere/rustdoc/not/required")

src/bootstrap/doc.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -405,14 +405,15 @@ impl Step for Standalone {
405405
cmd.arg("--html-after-content").arg(&footer)
406406
.arg("--html-before-content").arg(&version_info)
407407
.arg("--html-in-header").arg(&favicon)
408+
.arg("--markdown-no-toc")
409+
.arg("--index-page").arg(&builder.src.join("src/doc/index.md"))
408410
.arg("--markdown-playground-url")
409411
.arg("https://play.rust-lang.org/")
410412
.arg("-o").arg(&out)
411413
.arg(&path);
412414

413415
if filename == "not_found.md" {
414-
cmd.arg("--markdown-no-toc")
415-
.arg("--markdown-css")
416+
cmd.arg("--markdown-css")
416417
.arg("https://doc.rust-lang.org/rust.css");
417418
} else {
418419
cmd.arg("--markdown-css").arg("rust.css");
@@ -480,23 +481,31 @@ impl Step for Std {
480481
// will also directly handle merging.
481482
let my_out = builder.crate_doc_out(target);
482483
t!(symlink_dir_force(&builder.config, &my_out, &out_dir));
484+
t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
483485

484-
let mut cargo = builder.cargo(compiler, Mode::Std, target, "doc");
485-
compile::std_cargo(builder, &compiler, target, &mut cargo);
486+
let run_cargo_rustdoc_for = |package: &str| {
487+
let mut cargo = builder.cargo(compiler, Mode::Std, target, "rustdoc");
488+
compile::std_cargo(builder, &compiler, target, &mut cargo);
486489

487-
// Keep a whitelist so we do not build internal stdlib crates, these will be
488-
// build by the rustc step later if enabled.
489-
cargo.arg("--no-deps");
490-
for krate in &["alloc", "core", "std"] {
491-
cargo.arg("-p").arg(krate);
490+
// Keep a whitelist so we do not build internal stdlib crates, these will be
491+
// build by the rustc step later if enabled.
492+
cargo.arg("-Z").arg("unstable-options")
493+
.arg("-p").arg(package);
492494
// Create all crate output directories first to make sure rustdoc uses
493495
// relative links.
494496
// FIXME: Cargo should probably do this itself.
495-
t!(fs::create_dir_all(out_dir.join(krate)));
497+
t!(fs::create_dir_all(out_dir.join(package)));
498+
cargo.arg("--")
499+
.arg("--markdown-css").arg("rust.css")
500+
.arg("--markdown-no-toc")
501+
.arg("--index-page").arg(&builder.src.join("src/doc/index.md"));
502+
503+
builder.run(&mut cargo);
504+
builder.cp_r(&my_out, &out);
505+
};
506+
for krate in &["alloc", "core", "std"] {
507+
run_cargo_rustdoc_for(krate);
496508
}
497-
498-
builder.run(&mut cargo);
499-
builder.cp_r(&my_out, &out);
500509
}
501510
}
502511

src/doc/rustdoc/src/unstable-features.md

+24-11
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,22 @@ issue][issue-include].
197197
[unstable-include]: ../unstable-book/language-features/external-doc.html
198198
[issue-include]: https://github.com/rust-lang/rust/issues/44732
199199

200+
### Add aliases for an item in documentation search
201+
202+
This feature allows you to add alias(es) to an item when using the `rustdoc` search through the
203+
`doc(alias)` attribute. Example:
204+
205+
```rust,no_run
206+
#![feature(doc_alias)]
207+
208+
#[doc(alias = "x")]
209+
#[doc(alias = "big")]
210+
pub struct BigX;
211+
```
212+
213+
Then, when looking for it through the `rustdoc` search, if you enter "x" or
214+
"big", search will show the `BigX` struct first.
215+
200216
## Unstable command-line arguments
201217

202218
These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
@@ -374,18 +390,15 @@ This is an internal flag intended for the standard library and compiler that app
374390
allows `rustdoc` to be able to generate documentation for the compiler crates and the standard
375391
library, as an equivalent command-line argument is provided to `rustc` when building those crates.
376392

377-
### `doc_alias` feature
393+
### `--index-page`: provide a top-level landing page for docs
378394

379-
This feature allows you to add alias(es) to an item when using the `rustdoc` search through the
380-
`doc(alias)` attribute. Example:
395+
This feature allows you to generate an index-page with a given markdown file. A good example of it
396+
is the [rust documentation index](https://doc.rust-lang.org/index.html).
381397

382-
```rust,no_run
383-
#![feature(doc_alias)]
398+
With this, you'll have a page which you can custom as much as you want at the top of your crates.
384399

385-
#[doc(alias = "x")]
386-
#[doc(alias = "big")]
387-
pub struct BigX;
388-
```
400+
Using `index-page` option enables `enable-index-page` option as well.
389401

390-
Then, when looking for it through the `rustdoc` search, if you enter "x" or
391-
"big", search will show the `BigX` struct first.
402+
### `--enable-index-page`: generate a default index page for docs
403+
404+
This feature allows the generation of a default index-page which lists the generated crates.

src/librustdoc/html/render.rs

+74-12
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ use std::rc::Rc;
5454

5555
use externalfiles::ExternalHtml;
5656

57+
use errors;
58+
use getopts;
59+
5760
use serialize::json::{ToJson, Json, as_json};
5861
use syntax::ast;
5962
use syntax::ext::base::MacroKind;
@@ -106,6 +109,8 @@ struct Context {
106109
/// The map used to ensure all generated 'id=' attributes are unique.
107110
id_map: Rc<RefCell<IdMap>>,
108111
pub shared: Arc<SharedContext>,
112+
pub enable_index_page: bool,
113+
pub index_page: Option<PathBuf>,
109114
}
110115

111116
struct SharedContext {
@@ -501,7 +506,12 @@ pub fn run(mut krate: clean::Crate,
501506
sort_modules_alphabetically: bool,
502507
themes: Vec<PathBuf>,
503508
enable_minification: bool,
504-
id_map: IdMap) -> Result<(), Error> {
509+
id_map: IdMap,
510+
enable_index_page: bool,
511+
index_page: Option<PathBuf>,
512+
matches: &getopts::Matches,
513+
diag: &errors::Handler,
514+
) -> Result<(), Error> {
505515
let src_root = match krate.src {
506516
FileName::Real(ref p) => match p.parent() {
507517
Some(p) => p.to_path_buf(),
@@ -572,6 +582,8 @@ pub fn run(mut krate: clean::Crate,
572582
codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
573583
id_map: Rc::new(RefCell::new(id_map)),
574584
shared: Arc::new(scx),
585+
enable_index_page,
586+
index_page,
575587
};
576588

577589
// Crawl the crate to build various caches used for the output
@@ -666,7 +678,7 @@ pub fn run(mut krate: clean::Crate,
666678
CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone());
667679
CURRENT_LOCATION_KEY.with(|s| s.borrow_mut().clear());
668680

669-
write_shared(&cx, &krate, &*cache, index, enable_minification)?;
681+
write_shared(&cx, &krate, &*cache, index, enable_minification, matches, diag)?;
670682

671683
// And finally render the whole crate's documentation
672684
cx.krate(krate)
@@ -742,11 +754,15 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
742754
Json::Object(crate_data))
743755
}
744756

745-
fn write_shared(cx: &Context,
746-
krate: &clean::Crate,
747-
cache: &Cache,
748-
search_index: String,
749-
enable_minification: bool) -> Result<(), Error> {
757+
fn write_shared(
758+
cx: &Context,
759+
krate: &clean::Crate,
760+
cache: &Cache,
761+
search_index: String,
762+
enable_minification: bool,
763+
matches: &getopts::Matches,
764+
diag: &errors::Handler,
765+
) -> Result<(), Error> {
750766
// Write out the shared files. Note that these are shared among all rustdoc
751767
// docs placed in the output directory, so this needs to be a synchronized
752768
// operation with respect to all other rustdocs running around.
@@ -902,8 +918,9 @@ themePicker.onblur = handleThemeButtonsBlur;
902918
write(cx.dst.join("COPYRIGHT.txt"),
903919
include_bytes!("static/COPYRIGHT.txt"))?;
904920

905-
fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> {
921+
fn collect(path: &Path, krate: &str, key: &str) -> io::Result<(Vec<String>, Vec<String>)> {
906922
let mut ret = Vec::new();
923+
let mut krates = Vec::new();
907924
if path.exists() {
908925
for line in BufReader::new(File::open(path)?).lines() {
909926
let line = line?;
@@ -914,9 +931,13 @@ themePicker.onblur = handleThemeButtonsBlur;
914931
continue;
915932
}
916933
ret.push(line.to_string());
934+
krates.push(line[key.len() + 2..].split('"')
935+
.next()
936+
.map(|s| s.to_owned())
937+
.unwrap_or_else(|| String::new()));
917938
}
918939
}
919-
Ok(ret)
940+
Ok((ret, krates))
920941
}
921942

922943
fn show_item(item: &IndexItem, krate: &str) -> String {
@@ -931,7 +952,7 @@ themePicker.onblur = handleThemeButtonsBlur;
931952

932953
let dst = cx.dst.join("aliases.js");
933954
{
934-
let mut all_aliases = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
955+
let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
935956
let mut w = try_err!(File::create(&dst), &dst);
936957
let mut output = String::with_capacity(100);
937958
for (alias, items) in &cache.aliases {
@@ -955,7 +976,7 @@ themePicker.onblur = handleThemeButtonsBlur;
955976

956977
// Update the search index
957978
let dst = cx.dst.join("search-index.js");
958-
let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
979+
let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
959980
all_indexes.push(search_index);
960981
// Sort the indexes by crate so the file will be generated identically even
961982
// with rustdoc running in parallel.
@@ -969,6 +990,46 @@ themePicker.onblur = handleThemeButtonsBlur;
969990
}
970991
try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst);
971992

993+
if cx.enable_index_page == true {
994+
if let Some(ref index_page) = cx.index_page {
995+
::markdown::render(index_page,
996+
cx.dst.clone(),
997+
&matches, &(*cx.shared).layout.external_html,
998+
!matches.opt_present("markdown-no-toc"),
999+
diag);
1000+
} else {
1001+
let dst = cx.dst.join("index.html");
1002+
let mut w = BufWriter::new(try_err!(File::create(&dst), &dst));
1003+
let page = layout::Page {
1004+
title: "Index of crates",
1005+
css_class: "mod",
1006+
root_path: "./",
1007+
description: "List of crates",
1008+
keywords: BASIC_KEYWORDS,
1009+
resource_suffix: &cx.shared.resource_suffix,
1010+
};
1011+
krates.push(krate.name.clone());
1012+
krates.sort();
1013+
krates.dedup();
1014+
1015+
let content = format!(
1016+
"<h1 class='fqn'>\
1017+
<span class='in-band'>List of all crates</span>\
1018+
</h1><ul class='mod'>{}</ul>",
1019+
krates
1020+
.iter()
1021+
.map(|s| {
1022+
format!("<li><a href=\"{}/index.html\">{}</li>", s, s)
1023+
})
1024+
.collect::<String>());
1025+
try_err!(layout::render(&mut w, &cx.shared.layout,
1026+
&page, &(""), &content,
1027+
cx.shared.css_file_extension.is_some(),
1028+
&cx.shared.themes), &dst);
1029+
try_err!(w.flush(), &dst);
1030+
}
1031+
}
1032+
9721033
// Update the list of all implementors for traits
9731034
let dst = cx.dst.join("implementors");
9741035
for (&did, imps) in &cache.implementors {
@@ -1022,7 +1083,8 @@ themePicker.onblur = handleThemeButtonsBlur;
10221083
remote_item_type.css_class(),
10231084
remote_path[remote_path.len() - 1]));
10241085

1025-
let mut all_implementors = try_err!(collect(&mydst, &krate.name, "implementors"), &mydst);
1086+
let (mut all_implementors, _) = try_err!(collect(&mydst, &krate.name, "implementors"),
1087+
&mydst);
10261088
all_implementors.push(implementors);
10271089
// Sort the implementors by crate so the file will be generated
10281090
// identically even with rustdoc running in parallel.

0 commit comments

Comments
 (0)