diff options
| author | bors <bors@rust-lang.org> | 2014-06-30 07:31:29 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-06-30 07:31:29 +0000 |
| commit | 2735c7bb104d0938bccd261c5ea0d083f05ceba5 (patch) | |
| tree | b17bfa5031a983fc6fcb2cd4f6548d728773261e | |
| parent | e1683f50c00297e9908ae028fa1d41b9a52a6f6f (diff) | |
| parent | 63afc082629044755df0c416ecf4c20ef0375254 (diff) | |
| download | rust-2735c7bb104d0938bccd261c5ea0d083f05ceba5.tar.gz rust-2735c7bb104d0938bccd261c5ea0d083f05ceba5.zip | |
auto merge of #15237 : zzmp/rust/feat/markdown-in-crate-documentation, r=huonw
This makes the `in-header`, `markdown-before-content`, and `markdown-after-content` options available to `rustdoc` when generating documentation for any crate. Before, these options were only available when creating documentation *from* markdown. Now, they are available when generating documentation from source. This also updates the `rustdoc -h` output to reflect these changes. It does not update the `man rustdoc` page, nor does it update the documentation in [the `rustdoc` manual](http://doc.rust-lang.org/rustdoc.html).
| -rw-r--r-- | man/rustdoc.1 | 9 | ||||
| -rw-r--r-- | mk/docs.mk | 8 | ||||
| -rw-r--r-- | src/doc/rustdoc.md | 19 | ||||
| -rw-r--r-- | src/librustdoc/externalfiles.rs | 70 | ||||
| -rw-r--r-- | src/librustdoc/html/layout.rs | 11 | ||||
| -rw-r--r-- | src/librustdoc/html/render.rs | 8 | ||||
| -rw-r--r-- | src/librustdoc/lib.rs | 28 | ||||
| -rw-r--r-- | src/librustdoc/markdown.rs | 59 |
8 files changed, 143 insertions, 69 deletions
diff --git a/man/rustdoc.1 b/man/rustdoc.1 index 82b7ee27b94..d5795c328e7 100644 --- a/man/rustdoc.1 +++ b/man/rustdoc.1 @@ -38,6 +38,15 @@ directory to load plugins from (default: /tmp/rustdoc_ng/plugins) -L --library-path <val> directory to add to crate search path .TP +--html-in-header <val> +file to add to <head> +.TP +--html-before-content <val> +file to add in <body>, before content +.TP +--html-after-content <val> +file to add in <body>, after content +.TP -h, --help Print help diff --git a/mk/docs.mk b/mk/docs.mk index 8098a0682a5..213565b09ac 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -35,16 +35,16 @@ DOCS := index intro tutorial guide guide-ffi guide-macros guide-lifetimes \ PDF_DOCS := tutorial rust RUSTDOC_DEPS_rust := doc/full-toc.inc -RUSTDOC_FLAGS_rust := --markdown-in-header=doc/full-toc.inc +RUSTDOC_FLAGS_rust := --html-in-header=doc/full-toc.inc L10N_LANGS := ja # Generally no need to edit below here. # The options are passed to the documentation generators. -RUSTDOC_HTML_OPTS_NO_CSS = --markdown-before-content=doc/version_info.html \ - --markdown-in-header=doc/favicon.inc \ - --markdown-after-content=doc/footer.inc \ +RUSTDOC_HTML_OPTS_NO_CSS = --html-before-content=doc/version_info.html \ + --html-in-header=doc/favicon.inc \ + --html-after-content=doc/footer.inc \ --markdown-playground-url='http://play.rust-lang.org/' RUSTDOC_HTML_OPTS = $(RUSTDOC_HTML_OPTS_NO_CSS) --markdown-css rust.css diff --git a/src/doc/rustdoc.md b/src/doc/rustdoc.md index 2287bcabff7..8199eaea82c 100644 --- a/src/doc/rustdoc.md +++ b/src/doc/rustdoc.md @@ -103,6 +103,17 @@ rustdoc can also generate JSON, for consumption by other tools, with `rustdoc --output-format json`, and also consume already-generated JSON with `rustdoc --input-format json`. +rustdoc also supports personalizing the output from crates' documentation, +similar to markdown options. + +- `--html-in-header FILE`: includes the contents of `FILE` at the + end of the `<head>...</head>` section. +- `--html-before-content FILE`: includes the contents of `FILE` + directly after `<body>`, before the rendered content (including the + search bar). +- `--html-after-content FILE`: includes the contents of `FILE` + after all the rendered content. + # Using the Documentation The web pages generated by rustdoc present the same logical hierarchy that one @@ -238,16 +249,16 @@ detected by a `.md` or `.markdown` extension. There are 4 options to modify the output that Rustdoc creates. - `--markdown-css PATH`: adds a `<link rel="stylesheet">` tag pointing to `PATH`. -- `--markdown-in-header FILE`: includes the contents of `FILE` at the +- `--html-in-header FILE`: includes the contents of `FILE` at the end of the `<head>...</head>` section. -- `--markdown-before-content FILE`: includes the contents of `FILE` +- `--html-before-content FILE`: includes the contents of `FILE` directly after `<body>`, before the rendered content (including the title). -- `--markdown-after-content FILE`: includes the contents of `FILE` +- `--html-after-content FILE`: includes the contents of `FILE` directly before `</body>`, after all the rendered content. All of these can be specified multiple times, and they are output in -the order in which they are specified. The first line of the file must +the order in which they are specified. The first line of the file being rendered must be the title, prefixed with `%` (e.g. this page has `% Rust Documentation` on the first line). diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs new file mode 100644 index 00000000000..0931f132c02 --- /dev/null +++ b/src/librustdoc/externalfiles.rs @@ -0,0 +1,70 @@ +// Copyright 2014 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. + +use std::{io, str}; + +#[deriving(Clone)] +pub struct ExternalHtml{ + pub in_header: String, + pub before_content: String, + pub after_content: String +} + +impl ExternalHtml { + pub fn load(in_header: &[String], before_content: &[String], after_content: &[String]) + -> Option<ExternalHtml> { + match (load_external_files(in_header), + load_external_files(before_content), + load_external_files(after_content)) { + (Some(ih), Some(bc), Some(ac)) => Some(ExternalHtml { + in_header: ih, + before_content: bc, + after_content: ac + }), + _ => None + } + } +} + +pub fn load_string(input: &Path) -> io::IoResult<Option<String>> { + let mut f = try!(io::File::open(input)); + let d = try!(f.read_to_end()); + Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string())) +} + +macro_rules! load_or_return { + ($input: expr, $cant_read: expr, $not_utf8: expr) => { + { + let input = Path::new($input); + match ::externalfiles::load_string(&input) { + Err(e) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: {}", input.display(), e); + return $cant_read; + } + Ok(None) => { + let _ = writeln!(&mut io::stderr(), + "error reading `{}`: not UTF-8", input.display()); + return $not_utf8; + } + Ok(Some(s)) => s + } + } + } +} + +pub fn load_external_files(names: &[String]) -> Option<String> { + let mut out = String::new(); + for name in names.iter() { + out.push_str(load_or_return!(name.as_slice(), None, None).as_slice()); + out.push_char('\n'); + } + Some(out) +} diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 61a2d3c5d9c..aa298d07780 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -11,10 +11,13 @@ use std::fmt; use std::io; +use externalfiles::ExternalHtml; + #[deriving(Clone)] pub struct Layout { pub logo: String, pub favicon: String, + pub external_html: ExternalHtml, pub krate: String, pub playground_url: String, } @@ -44,6 +47,7 @@ r##"<!DOCTYPE html> <link rel="stylesheet" type="text/css" href="{root_path}main.css"> {favicon} + {in_header} </head> <body> <!--[if lte IE 8]> @@ -53,6 +57,8 @@ r##"<!DOCTYPE html> </div> <![endif]--> + {before_content} + <section class="sidebar"> {logo} {sidebar} @@ -105,6 +111,8 @@ r##"<!DOCTYPE html> </div> </div> + {after_content} + <script> window.rootPath = "{root_path}"; window.currentCrate = "{krate}"; @@ -133,6 +141,9 @@ r##"<!DOCTYPE html> } else { format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon) }, + in_header = layout.external_html.in_header, + before_content = layout.external_html.before_content, + after_content = layout.external_html.after_content, sidebar = *sidebar, krate = layout.krate, play_url = layout.playground_url, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index aacb13156b7..f5d379c4baf 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -41,6 +41,8 @@ use std::str; use std::string::String; use std::sync::Arc; +use externalfiles::ExternalHtml; + use serialize::json::ToJson; use syntax::ast; use syntax::ast_util; @@ -78,7 +80,7 @@ pub struct Context { /// This changes as the context descends into the module hierarchy. pub dst: Path, /// This describes the layout of each page, and is not modified after - /// creation of the context (contains info like the favicon) + /// creation of the context (contains info like the favicon and added html). pub layout: layout::Layout, /// This map is a list of what should be displayed on the sidebar of the /// current page. The key is the section header (traits, modules, @@ -220,7 +222,7 @@ local_data_key!(pub cache_key: Arc<Cache>) local_data_key!(pub current_location_key: Vec<String> ) /// Generates the documentation for `crate` into the directory `dst` -pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { +pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: Path) -> io::IoResult<()> { let mut cx = Context { dst: dst, current: Vec::new(), @@ -229,12 +231,14 @@ pub fn run(mut krate: clean::Crate, dst: Path) -> io::IoResult<()> { layout: layout::Layout { logo: "".to_string(), favicon: "".to_string(), + external_html: external_html.clone(), krate: krate.name.clone(), playground_url: "".to_string(), }, include_sources: true, render_redirect_pages: false, }; + try!(mkdir(&cx.dst)); // Crawl the crate attributes looking for attributes which control how we're diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index be14ffa87af..46aa6cb5e94 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,6 +32,7 @@ use std::io::{File, MemWriter}; use std::str; use std::gc::Gc; use serialize::{json, Decodable, Encodable}; +use externalfiles::ExternalHtml; // reexported from `clean` so it can be easily updated with the mod itself pub use clean::SCHEMA_VERSION; @@ -39,6 +40,8 @@ pub use clean::SCHEMA_VERSION; pub mod clean; pub mod core; pub mod doctree; +#[macro_escape] +pub mod externalfiles; pub mod fold; pub mod html { pub mod highlight; @@ -113,16 +116,17 @@ pub fn opts() -> Vec<getopts::OptGroup> { "ARGS"), optmulti("", "markdown-css", "CSS files to include via <link> in a rendered Markdown file", "FILES"), - optmulti("", "markdown-in-header", - "files to include inline in the <head> section of a rendered Markdown file", + optmulti("", "html-in-header", + "files to include inline in the <head> section of a rendered Markdown file \ + or generated documentation", "FILES"), - optmulti("", "markdown-before-content", + optmulti("", "html-before-content", "files to include inline between <body> and the content of a rendered \ - Markdown file", + Markdown file or generated documentation", "FILES"), - optmulti("", "markdown-after-content", + optmulti("", "html-after-content", "files to include inline between the content and </body> of a rendered \ - Markdown file", + Markdown file or generated documentation", "FILES"), optopt("", "markdown-playground-url", "URL to send code snippets to", "URL") @@ -179,6 +183,14 @@ pub fn main_args(args: &[String]) -> int { let output = matches.opt_str("o").map(|s| Path::new(s)); let cfgs = matches.opt_strs("cfg"); + let external_html = match ExternalHtml::load( + matches.opt_strs("html-in-header").as_slice(), + matches.opt_strs("html-before-content").as_slice(), + matches.opt_strs("html-after-content").as_slice()) { + Some(eh) => eh, + None => return 3 + }; + match (should_test, markdown_input) { (true, true) => { return markdown::test(input, libs, test_args) @@ -187,7 +199,7 @@ pub fn main_args(args: &[String]) -> int { return test::run(input, cfgs, libs, test_args) } (false, true) => return markdown::render(input, output.unwrap_or(Path::new("doc")), - &matches), + &matches, &external_html), (false, false) => {} } @@ -215,7 +227,7 @@ pub fn main_args(args: &[String]) -> int { let started = time::precise_time_ns(); match matches.opt_str("w").as_ref().map(|s| s.as_slice()) { Some("html") | None => { - match html::render::run(krate, output.unwrap_or(Path::new("doc"))) { + match html::render::run(krate, &external_html, output.unwrap_or(Path::new("doc"))) { Ok(()) => {} Err(e) => fail!("failed to generate documentation: {}", e), } diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 76366240f1a..da271be4768 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -9,43 +9,19 @@ // except according to those terms. use std::collections::HashSet; -use std::{str, io}; +use std::io; use std::string::String; use getopts; use testing; +use externalfiles::ExternalHtml; + use html::escape::Escape; use html::markdown; use html::markdown::{MarkdownWithToc, find_testable_code, reset_headers}; use test::Collector; -fn load_string(input: &Path) -> io::IoResult<Option<String>> { - let mut f = try!(io::File::open(input)); - let d = try!(f.read_to_end()); - Ok(str::from_utf8(d.as_slice()).map(|s| s.to_string())) -} -macro_rules! load_or_return { - ($input: expr, $cant_read: expr, $not_utf8: expr) => { - { - let input = Path::new($input); - match load_string(&input) { - Err(e) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: {}", input.display(), e); - return $cant_read; - } - Ok(None) => { - let _ = writeln!(&mut io::stderr(), - "error reading `{}`: not UTF-8", input.display()); - return $not_utf8; - } - Ok(Some(s)) => s - } - } - } -} - /// Separate any lines at the start of the file that begin with `%`. fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { let mut metadata = Vec::new(); @@ -62,18 +38,10 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { (metadata, "") } -fn load_external_files(names: &[String]) -> Option<String> { - let mut out = String::new(); - for name in names.iter() { - out.push_str(load_or_return!(name.as_slice(), None, None).as_slice()); - out.push_char('\n'); - } - Some(out) -} - /// Render `input` (e.g. "foo.md") into an HTML file in `output` /// (e.g. output = "bar" => "bar/foo.html"). -pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int { +pub fn render(input: &str, mut output: Path, matches: &getopts::Matches, + external_html: &ExternalHtml) -> int { let input_p = Path::new(input); output.push(input_p.filestem().unwrap()); output.set_extension("html"); @@ -91,17 +59,6 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int } let playground = playground.unwrap_or("".to_string()); - let (in_header, before_content, after_content) = - match (load_external_files(matches.opt_strs("markdown-in-header") - .as_slice()), - load_external_files(matches.opt_strs("markdown-before-content") - .as_slice()), - load_external_files(matches.opt_strs("markdown-after-content") - .as_slice())) { - (Some(a), Some(b), Some(c)) => (a,b,c), - _ => return 3 - }; - let mut out = match io::File::create(&output) { Err(e) => { let _ = writeln!(&mut io::stderr(), @@ -153,10 +110,10 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int </html>"#, title = Escape(title), css = css, - in_header = in_header, - before_content = before_content, + in_header = external_html.in_header, + before_content = external_html.before_content, text = MarkdownWithToc(text), - after_content = after_content, + after_content = external_html.after_content, playground = playground, ); |
