]> git.lizzy.rs Git - rust.git/commitdiff
Add index page
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Mon, 24 Sep 2018 23:08:33 +0000 (01:08 +0200)
committerGuillaume Gomez <guillaume1.gomez@gmail.com>
Sat, 20 Oct 2018 23:15:11 +0000 (01:15 +0200)
src/bootstrap/doc.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs

index 17ccb04a7146d861a8eaaaccbad16e71a42bf07a..5e02444490cbad61514e513ff0beefa1ae3be6ea 100644 (file)
@@ -405,6 +405,7 @@ fn run(self, builder: &Builder) {
             cmd.arg("--html-after-content").arg(&footer)
                .arg("--html-before-content").arg(&version_info)
                .arg("--html-in-header").arg(&favicon)
+               .arg("--index-page").arg("src/doc/index.md")
                .arg("--markdown-playground-url")
                .arg("https://play.rust-lang.org/")
                .arg("-o").arg(&out)
index dda0f37c3f95bfeffaaaf4e3c7e4d5616fd2f5ab..6436189bbf105bc27d68dc0c5e2379732ea58c64 100644 (file)
@@ -80,6 +80,8 @@
 
 use minifier;
 
+use pulldown_cmark;
+
 /// A pair of name and its optional document.
 pub type NameDoc = (String, Option<String>);
 
@@ -106,6 +108,8 @@ struct Context {
     /// The map used to ensure all generated 'id=' attributes are unique.
     id_map: Rc<RefCell<IdMap>>,
     pub shared: Arc<SharedContext>,
+    pub enable_index_page: bool,
+    pub index_page: Option<PathBuf>,
 }
 
 struct SharedContext {
@@ -501,7 +505,10 @@ pub fn run(mut krate: clean::Crate,
            sort_modules_alphabetically: bool,
            themes: Vec<PathBuf>,
            enable_minification: bool,
-           id_map: IdMap) -> Result<(), Error> {
+           id_map: IdMap,
+           enable_index_page: bool,
+           index_page: Option<PathBuf>,
+) -> Result<(), Error> {
     let src_root = match krate.src {
         FileName::Real(ref p) => match p.parent() {
             Some(p) => p.to_path_buf(),
@@ -572,6 +579,8 @@ pub fn run(mut krate: clean::Crate,
         codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()),
         id_map: Rc::new(RefCell::new(id_map)),
         shared: Arc::new(scx),
+        enable_index_page,
+        index_page,
     };
 
     // Crawl the crate to build various caches used for the output
@@ -902,8 +911,9 @@ fn write_shared(cx: &Context,
     write(cx.dst.join("COPYRIGHT.txt"),
           include_bytes!("static/COPYRIGHT.txt"))?;
 
-    fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> {
+    fn collect(path: &Path, krate: &str, key: &str) -> io::Result<(Vec<String>, Vec<String>)> {
         let mut ret = Vec::new();
+        let mut krates = Vec::new();
         if path.exists() {
             for line in BufReader::new(File::open(path)?).lines() {
                 let line = line?;
@@ -914,9 +924,13 @@ fn collect(path: &Path, krate: &str, key: &str) -> io::Result<Vec<String>> {
                     continue;
                 }
                 ret.push(line.to_string());
+                krates.push(line[key.len() + 2..].split('"')
+                                                 .next()
+                                                 .map(|s| s.to_owned())
+                                                 .unwrap_or_else(|| String::new()));
             }
         }
-        Ok(ret)
+        Ok((ret, krates))
     }
 
     fn show_item(item: &IndexItem, krate: &str) -> String {
@@ -931,7 +945,7 @@ fn show_item(item: &IndexItem, krate: &str) -> String {
 
     let dst = cx.dst.join("aliases.js");
     {
-        let mut all_aliases = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
+        let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst);
         let mut w = try_err!(File::create(&dst), &dst);
         let mut output = String::with_capacity(100);
         for (alias, items) in &cache.aliases {
@@ -955,7 +969,7 @@ fn show_item(item: &IndexItem, krate: &str) -> String {
 
     // Update the search index
     let dst = cx.dst.join("search-index.js");
-    let mut all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
+    let (mut all_indexes, mut krates) = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
     all_indexes.push(search_index);
     // Sort the indexes by crate so the file will be generated identically even
     // with rustdoc running in parallel.
@@ -969,6 +983,61 @@ fn show_item(item: &IndexItem, krate: &str) -> String {
     }
     try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst);
 
+<<<<<<< HEAD
+    if cx.disable_index_page == false {
+        let dst = cx.dst.join("index.html");
+=======
+    if cx.enable_index_page == true {
+>>>>>>> a2642cf... f
+        if let Some(ref index_page) = cx.index_page {
+            let mut content = Vec::with_capacity(100000);
+
+            let mut f = try_err!(File::open(&index_page), &index_page);
+            try_err!(f.read_to_end(&mut content), &index_page);
+            let content = match String::from_utf8(content) {
+                Ok(c) => c,
+                Err(_) => return Err(Error::new(
+                                         io::Error::new(
+                                             io::ErrorKind::Other, "invalid markdown"),
+                                             &index_page)),
+            };
+            let parser = pulldown_cmark::Parser::new(&content);
+            let mut html_buf = String::new();
+            pulldown_cmark::html::push_html(&mut html_buf, parser);
+            let mut f = try_err!(File::create(&dst), &dst);
+            try_err!(f.write_all(html_buf.as_bytes()), &dst);
+        } else {
+            let mut w = BufWriter::new(try_err!(File::create(&dst), &dst));
+            let page = layout::Page {
+                title: "Index of crates",
+                css_class: "mod",
+                root_path: "./",
+                description: "List of crates",
+                keywords: BASIC_KEYWORDS,
+                resource_suffix: &cx.shared.resource_suffix,
+            };
+            krates.push(krate.name.clone());
+            krates.sort();
+            krates.dedup();
+
+            let content = format!(
+"<h1 class='fqn'>\
+     <span class='in-band'>List of all crates</span>\
+</h1><ul class='mod'>{}</ul>",
+                                  krates
+                                    .iter()
+                                    .map(|s| {
+                                        format!("<li><a href=\"{}/index.html\">{}</li>", s, s)
+                                    })
+                                    .collect::<String>());
+            try_err!(layout::render(&mut w, &cx.shared.layout,
+                                    &page, &(""), &content,
+                                    cx.shared.css_file_extension.is_some(),
+                                    &cx.shared.themes), &dst);
+            try_err!(w.flush(), &dst);
+        }
+    }
+
     // Update the list of all implementors for traits
     let dst = cx.dst.join("implementors");
     for (&did, imps) in &cache.implementors {
@@ -1022,7 +1091,8 @@ fn show_item(item: &IndexItem, krate: &str) -> String {
                             remote_item_type.css_class(),
                             remote_path[remote_path.len() - 1]));
 
-        let mut all_implementors = try_err!(collect(&mydst, &krate.name, "implementors"), &mydst);
+        let (mut all_implementors, _) = try_err!(collect(&mydst, &krate.name, "implementors"),
+                                                 &mydst);
         all_implementors.push(implementors);
         // Sort the implementors by crate so the file will be generated
         // identically even with rustdoc running in parallel.
index 406180c09e8e48b26c0cc7d8ab2ccb732b57d4e1..cb9fb94db7c16cf29b1a80644ee14d5b468052e5 100644 (file)
@@ -334,6 +334,17 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
+        unstable("index-page", |o| {
+             o.optopt("",
+                      "index-page",
+                      "Markdown file to be used as index page",
+                      "PATH")
+        }),
+        unstable("enable-index-page", |o| {
+             o.optflag("",
+                       "enable-index-page",
+                       "To enable generation of the index page")
+        }),
     ]
 }
 
@@ -534,6 +545,8 @@ fn main_args(args: &[String]) -> isize {
     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");
+    let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s));
+    let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
     let enable_minification = !matches.opt_present("disable-minification");
 
     let edition = matches.opt_str("edition").unwrap_or("2015".to_string());
@@ -544,6 +557,12 @@ fn main_args(args: &[String]) -> isize {
             return 1;
         }
     };
+    if let Some(ref index_page) = index_page {
+        if !index_page.is_file() {
+            diag.struct_err("option `--index-page` argument must be a file").emit();
+            return 1;
+        }
+    }
 
     let cg = build_codegen_options(&matches, ErrorOutputType::default());
 
@@ -580,7 +599,10 @@ fn main_args(args: &[String]) -> isize {
                                   renderinfo,
                                   sort_modules_alphabetically,
                                   themes,
-                                  enable_minification, id_map)
+                                  enable_minification, id_map,
+                                  enable_index_page, index_page,
+                                  &matches,
+                                  &diag)
                     .expect("failed to generate documentation");
                 0
             }