1 use clap
::crate_version
;
4 use std
::path
::{Path, PathBuf}
;
6 use clap
::{App, AppSettings, ArgMatches, SubCommand}
;
8 use mdbook
::errors
::Result
as Result3
;
11 #[cfg(feature = "linkcheck")]
13 #[cfg(feature = "linkcheck")]
14 use mdbook
::renderer
::RenderContext
;
15 #[cfg(feature = "linkcheck")]
16 use mdbook_linkcheck
::{self, errors::BrokenLinks}
;
19 let d_message
= "-d, --dest-dir=[dest-dir]
20 'The output directory for your book{n}(Defaults to ./book when omitted)'";
21 let dir_message
= "[dir]
22 'A directory for your book{n}(Defaults to Current Directory when omitted)'";
24 let matches
= App
::new("rustbook")
25 .about("Build a book with mdBook")
26 .author("Steve Klabnik <steve@steveklabnik.com>")
27 .version(&*format
!("v{}", crate_version
!()))
28 .setting(AppSettings
::SubcommandRequired
)
30 SubCommand
::with_name("build")
31 .about("Build the book from the markdown files")
32 .arg_from_usage(d_message
)
33 .arg_from_usage(dir_message
),
36 SubCommand
::with_name("linkcheck")
37 .about("Run linkcheck with mdBook 3")
38 .arg_from_usage(dir_message
),
42 // Check which subcomamnd the user ran...
43 match matches
.subcommand() {
44 ("build", Some(sub_matches
)) => {
45 if let Err(e
) = build(sub_matches
) {
46 eprintln
!("Error: {}", e
);
48 for cause
in e
.iter().skip(1) {
49 eprintln
!("\tCaused By: {}", cause
);
52 ::std
::process
::exit(101);
55 ("linkcheck", Some(sub_matches
)) => {
56 #[cfg(feature = "linkcheck")]
58 if let Err(err
) = linkcheck(sub_matches
) {
59 eprintln
!("Error: {}", err
);
61 // HACK: ignore timeouts
62 let actually_broken
= err
63 .downcast
::<BrokenLinks
>()
68 .inspect(|cause
| eprintln
!("\tCaused By: {}", cause
))
69 .fold(false, |already_broken
, cause
| {
70 already_broken
|| !format
!("{}", cause
).contains("timed out")
76 std
::process
::exit(101);
78 std
::process
::exit(0);
83 #[cfg(not(feature = "linkcheck"))]
85 // This avoids the `unused_binding` lint.
87 "mdbook-linkcheck is disabled, but arguments were passed: {:?}",
92 (_
, _
) => unreachable
!(),
96 #[cfg(feature = "linkcheck")]
97 pub fn linkcheck(args
: &ArgMatches
<'_
>) -> Result
<(), Error
> {
98 let book_dir
= get_book_dir(args
);
99 let book
= MDBook
::load(&book_dir
).unwrap();
100 let cfg
= book
.config
;
101 let render_ctx
= RenderContext
::new(&book_dir
, book
.book
, cfg
, &book_dir
);
103 mdbook_linkcheck
::check_links(&render_ctx
)
106 // Build command implementation
107 pub fn build(args
: &ArgMatches
<'_
>) -> Result3
<()> {
108 let book_dir
= get_book_dir(args
);
109 let mut book
= MDBook
::load(&book_dir
)?
;
111 // Set this to allow us to catch bugs in advance.
112 book
.config
.build
.create_missing
= false;
114 if let Some(dest_dir
) = args
.value_of("dest-dir") {
115 book
.config
.build
.build_dir
= PathBuf
::from(dest_dir
);
123 fn get_book_dir(args
: &ArgMatches
<'_
>) -> PathBuf
{
124 if let Some(dir
) = args
.value_of("dir") {
125 // Check if path is relative from current dir, or absolute...
126 let p
= Path
::new(dir
);
128 env
::current_dir().unwrap().join(dir
)
133 env
::current_dir().unwrap()