1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use std
::default::Default
;
13 use std
::io
::prelude
::*;
14 use std
::path
::{PathBuf, Path}
;
18 use rustc
::session
::search_paths
::SearchPaths
;
19 use rustc
::session
::config
::Externs
;
20 use syntax
::codemap
::DUMMY_SP
;
22 use externalfiles
::{ExternalHtml, LoadStringError, load_string}
;
24 use html
::render
::reset_ids
;
25 use html
::escape
::Escape
;
27 use html
::markdown
::{Markdown, MarkdownWithToc, find_testable_code, old_find_testable_code}
;
28 use html
::markdown
::RenderType
;
29 use test
::{TestOptions, Collector}
;
31 /// Separate any lines at the start of the file that begin with `# ` or `%`.
32 fn extract_leading_metadata
<'a
>(s
: &'a
str) -> (Vec
<&'a
str>, &'a
str) {
33 let mut metadata
= Vec
::new();
36 for line
in s
.lines() {
37 if line
.starts_with("# ") || line
.starts_with("%") {
38 // trim the whitespace after the symbol
39 metadata
.push(line
[1..].trim_left());
40 count
+= line
.len() + 1;
42 return (metadata
, &s
[count
..]);
46 // if we're here, then all lines were metadata `# ` or `%` lines.
50 /// Render `input` (e.g. "foo.md") into an HTML file in `output`
51 /// (e.g. output = "bar" => "bar/foo.html").
52 pub fn render(input
: &str, mut output
: PathBuf
, matches
: &getopts
::Matches
,
53 external_html
: &ExternalHtml
, include_toc
: bool
,
54 render_type
: RenderType
) -> isize {
55 let input_p
= Path
::new(input
);
56 output
.push(input_p
.file_stem().unwrap());
57 output
.set_extension("html");
59 let mut css
= String
::new();
60 for name
in &matches
.opt_strs("markdown-css") {
61 let s
= format
!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", name
);
65 let input_str
= match load_string(input
) {
67 Err(LoadStringError
::ReadFail
) => return 1,
68 Err(LoadStringError
::BadUtf8
) => return 2,
70 if let Some(playground
) = matches
.opt_str("markdown-playground-url").or(
71 matches
.opt_str("playground-url")) {
72 markdown
::PLAYGROUND
.with(|s
| { *s.borrow_mut() = Some((None, playground)); }
);
75 let mut out
= match File
::create(&output
) {
77 eprintln
!("rustdoc: {}: {}", output
.display(), e
);
83 let (metadata
, text
) = extract_leading_metadata(&input_str
);
84 if metadata
.is_empty() {
85 eprintln
!("rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`");
88 let title
= metadata
[0];
92 let rendered
= if include_toc
{
93 format
!("{}", MarkdownWithToc(text
, render_type
))
95 format
!("{}", Markdown(text
, render_type
))
103 <meta charset="utf-8">
104 <meta name="viewport" content="width=device-width, initial-scale=1.0">
105 <meta name="generator" content="rustdoc">
106 <title>{title}</title>
111 <body class="rustdoc">
113 <div class="warning">
114 This old browser is unsupported and will most likely display funky
120 <h1 class="title">{title}</h1>
125 title
= Escape(title
),
127 in_header
= external_html
.in_header
,
128 before_content
= external_html
.before_content
,
130 after_content
= external_html
.after_content
,
135 eprintln
!("rustdoc: cannot write to `{}`: {}", output
.display(), e
);
142 /// Run any tests/code examples in the markdown file `input`.
143 pub fn test(input
: &str, cfgs
: Vec
<String
>, libs
: SearchPaths
, externs
: Externs
,
144 mut test_args
: Vec
<String
>, maybe_sysroot
: Option
<PathBuf
>,
145 render_type
: RenderType
, display_warnings
: bool
, linker
: Option
<String
>) -> isize {
146 let input_str
= match load_string(input
) {
148 Err(LoadStringError
::ReadFail
) => return 1,
149 Err(LoadStringError
::BadUtf8
) => return 2,
152 let mut opts
= TestOptions
::default();
153 opts
.no_crate_inject
= true;
154 let mut collector
= Collector
::new(input
.to_string(), cfgs
, libs
, externs
,
155 true, opts
, maybe_sysroot
, None
,
156 Some(input
.to_owned()),
157 render_type
, linker
);
158 if render_type
== RenderType
::Pulldown
{
159 old_find_testable_code(&input_str
, &mut collector
, DUMMY_SP
);
160 find_testable_code(&input_str
, &mut collector
, DUMMY_SP
);
162 old_find_testable_code(&input_str
, &mut collector
, DUMMY_SP
);
164 test_args
.insert(0, "rustdoctest".to_string());
165 testing
::test_main(&test_args
, collector
.tests
,
166 testing
::Options
::new().display_output(display_warnings
));