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).
This commit is contained in:
commit
2735c7bb10
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
||||
|
70
src/librustdoc/externalfiles.rs
Normal file
70
src/librustdoc/externalfiles.rs
Normal file
@ -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)
|
||||
}
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user