]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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. | |
4 | // | |
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. | |
10 | ||
9346a6ac | 11 | use std::default::Default; |
c34b1796 | 12 | use std::fs::File; |
c34b1796 | 13 | use std::io::prelude::*; |
9346a6ac | 14 | use std::io; |
c34b1796 | 15 | use std::path::{PathBuf, Path}; |
1a4d82fc JJ |
16 | |
17 | use core; | |
18 | use getopts; | |
19 | use testing; | |
20 | use rustc::session::search_paths::SearchPaths; | |
21 | ||
22 | use externalfiles::ExternalHtml; | |
23 | ||
92a42be0 | 24 | use html::render::reset_ids; |
1a4d82fc JJ |
25 | use html::escape::Escape; |
26 | use html::markdown; | |
92a42be0 | 27 | use html::markdown::{Markdown, MarkdownWithToc, find_testable_code}; |
9346a6ac | 28 | use test::{TestOptions, Collector}; |
1a4d82fc JJ |
29 | |
30 | /// Separate any lines at the start of the file that begin with `%`. | |
31 | fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { | |
32 | let mut metadata = Vec::new(); | |
c1a9b12d | 33 | let mut count = 0; |
1a4d82fc JJ |
34 | for line in s.lines() { |
35 | if line.starts_with("%") { | |
36 | // remove %<whitespace> | |
c1a9b12d SL |
37 | metadata.push(line[1..].trim_left()); |
38 | count += line.len() + 1; | |
1a4d82fc | 39 | } else { |
c1a9b12d | 40 | return (metadata, &s[count..]); |
1a4d82fc JJ |
41 | } |
42 | } | |
43 | // if we're here, then all lines were metadata % lines. | |
44 | (metadata, "") | |
45 | } | |
46 | ||
47 | /// Render `input` (e.g. "foo.md") into an HTML file in `output` | |
48 | /// (e.g. output = "bar" => "bar/foo.html"). | |
c34b1796 AL |
49 | pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches, |
50 | external_html: &ExternalHtml, include_toc: bool) -> isize { | |
1a4d82fc | 51 | let input_p = Path::new(input); |
c34b1796 | 52 | output.push(input_p.file_stem().unwrap()); |
1a4d82fc JJ |
53 | output.set_extension("html"); |
54 | ||
55 | let mut css = String::new(); | |
85aaf69f | 56 | for name in &matches.opt_strs("markdown-css") { |
1a4d82fc | 57 | let s = format!("<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", name); |
85aaf69f | 58 | css.push_str(&s) |
1a4d82fc JJ |
59 | } |
60 | ||
61 | let input_str = load_or_return!(input, 1, 2); | |
62 | let playground = matches.opt_str("markdown-playground-url"); | |
63 | if playground.is_some() { | |
9346a6ac | 64 | markdown::PLAYGROUND_KRATE.with(|s| { *s.borrow_mut() = Some(None); }); |
1a4d82fc JJ |
65 | } |
66 | let playground = playground.unwrap_or("".to_string()); | |
67 | ||
c34b1796 | 68 | let mut out = match File::create(&output) { |
1a4d82fc | 69 | Err(e) => { |
c34b1796 | 70 | let _ = writeln!(&mut io::stderr(), |
1a4d82fc JJ |
71 | "error opening `{}` for writing: {}", |
72 | output.display(), e); | |
73 | return 4; | |
74 | } | |
75 | Ok(f) => f | |
76 | }; | |
77 | ||
85aaf69f | 78 | let (metadata, text) = extract_leading_metadata(&input_str); |
9346a6ac | 79 | if metadata.is_empty() { |
c34b1796 | 80 | let _ = writeln!(&mut io::stderr(), |
1a4d82fc JJ |
81 | "invalid markdown file: expecting initial line with `% ...TITLE...`"); |
82 | return 5; | |
83 | } | |
85aaf69f | 84 | let title = metadata[0]; |
1a4d82fc | 85 | |
54a0048b | 86 | reset_ids(false); |
1a4d82fc JJ |
87 | |
88 | let rendered = if include_toc { | |
89 | format!("{}", MarkdownWithToc(text)) | |
90 | } else { | |
91 | format!("{}", Markdown(text)) | |
92 | }; | |
93 | ||
94 | let err = write!( | |
95 | &mut out, | |
96 | r#"<!DOCTYPE html> | |
97 | <html lang="en"> | |
98 | <head> | |
99 | <meta charset="utf-8"> | |
85aaf69f | 100 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
1a4d82fc JJ |
101 | <meta name="generator" content="rustdoc"> |
102 | <title>{title}</title> | |
103 | ||
104 | {css} | |
105 | {in_header} | |
106 | </head> | |
107 | <body class="rustdoc"> | |
108 | <!--[if lte IE 8]> | |
109 | <div class="warning"> | |
110 | This old browser is unsupported and will most likely display funky | |
111 | things. | |
112 | </div> | |
113 | <![endif]--> | |
114 | ||
115 | {before_content} | |
116 | <h1 class="title">{title}</h1> | |
117 | {text} | |
118 | <script type="text/javascript"> | |
119 | window.playgroundUrl = "{playground}"; | |
120 | </script> | |
121 | {after_content} | |
122 | </body> | |
123 | </html>"#, | |
124 | title = Escape(title), | |
125 | css = css, | |
126 | in_header = external_html.in_header, | |
127 | before_content = external_html.before_content, | |
128 | text = rendered, | |
129 | after_content = external_html.after_content, | |
130 | playground = playground, | |
131 | ); | |
132 | ||
133 | match err { | |
134 | Err(e) => { | |
c34b1796 | 135 | let _ = writeln!(&mut io::stderr(), |
1a4d82fc JJ |
136 | "error writing to `{}`: {}", |
137 | output.display(), e); | |
138 | 6 | |
139 | } | |
140 | Ok(_) => 0 | |
141 | } | |
142 | } | |
143 | ||
144 | /// Run any tests/code examples in the markdown file `input`. | |
92a42be0 | 145 | pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: core::Externs, |
c34b1796 | 146 | mut test_args: Vec<String>) -> isize { |
1a4d82fc JJ |
147 | let input_str = load_or_return!(input, 1, 2); |
148 | ||
9346a6ac AL |
149 | let mut opts = TestOptions::default(); |
150 | opts.no_crate_inject = true; | |
92a42be0 | 151 | let mut collector = Collector::new(input.to_string(), cfgs, libs, externs, |
9346a6ac | 152 | true, opts); |
85aaf69f | 153 | find_testable_code(&input_str, &mut collector); |
1a4d82fc | 154 | test_args.insert(0, "rustdoctest".to_string()); |
85aaf69f | 155 | testing::test_main(&test_args, collector.tests); |
1a4d82fc JJ |
156 | 0 |
157 | } |