@@ -8,8 +8,6 @@ use clap::{App, AppSettings, ArgMatches, SubCommand};
88use mdbook:: errors:: Result as Result3 ;
99use mdbook:: MDBook ;
1010
11- #[ cfg( feature = "linkcheck" ) ]
12- use failure:: Error ;
1311#[ cfg( feature = "linkcheck" ) ]
1412use mdbook:: renderer:: RenderContext ;
1513
@@ -53,8 +51,18 @@ fn main() {
5351 ( "linkcheck" , Some ( sub_matches) ) => {
5452 #[ cfg( feature = "linkcheck" ) ]
5553 {
56- if let Err ( err) = linkcheck ( sub_matches) {
57- eprintln ! ( "Error: {}" , err) ;
54+ let ( diags, files) = linkcheck ( sub_matches) . expect ( "Error while linkchecking." ) ;
55+ if !diags. is_empty ( ) {
56+ let color = codespan_reporting:: term:: termcolor:: ColorChoice :: Auto ;
57+ let mut writer =
58+ codespan_reporting:: term:: termcolor:: StandardStream :: stderr ( color) ;
59+ let cfg = codespan_reporting:: term:: Config :: default ( ) ;
60+
61+ for diag in diags {
62+ codespan_reporting:: term:: emit ( & mut writer, & cfg, & files, & diag)
63+ . expect ( "Unable to emit linkcheck error." ) ;
64+ }
65+
5866 std:: process:: exit ( 101 ) ;
5967 }
6068 }
@@ -73,14 +81,57 @@ fn main() {
7381}
7482
7583#[ cfg( feature = "linkcheck" ) ]
76- pub fn linkcheck ( args : & ArgMatches < ' _ > ) -> Result < ( ) , Error > {
84+ pub fn linkcheck (
85+ args : & ArgMatches < ' _ > ,
86+ ) -> Result < ( Vec < codespan_reporting:: diagnostic:: Diagnostic > , codespan:: Files ) , failure:: Error > {
87+ use mdbook_linkcheck:: Reason ;
88+
7789 let book_dir = get_book_dir ( args) ;
90+ let src_dir = get_book_dir ( args) . join ( "src" ) ;
7891 let book = MDBook :: load ( & book_dir) . unwrap ( ) ;
79- let cfg = book. config ;
80- let render_ctx = RenderContext :: new ( & book_dir, book. book , cfg, & book_dir) ;
92+ let linkck_cfg = mdbook_linkcheck:: get_config ( & book. config ) ?;
93+ let mut files = codespan:: Files :: new ( ) ;
94+ let target_files = mdbook_linkcheck:: load_files_into_memory ( & book. book , & mut files) ;
95+ let render_ctx = RenderContext :: new ( & book_dir, book. book , book. config , & book_dir) ;
8196 let cache_file = render_ctx. destination . join ( "cache.json" ) ;
82- let color = codespan_reporting:: term:: termcolor:: ColorChoice :: Auto ;
83- mdbook_linkcheck:: run ( & cache_file, color, & render_ctx)
97+ let cache = mdbook_linkcheck:: Cache :: load ( std:: fs:: File :: open ( cache_file) ?) ?;
98+
99+ let ( links, incomplete) = mdbook_linkcheck:: extract_links ( target_files, & files) ;
100+
101+ let outcome =
102+ mdbook_linkcheck:: validate ( & links, & linkck_cfg, & src_dir, & cache, & files, incomplete) ?;
103+
104+ let mut is_real_error = false ;
105+
106+ for link in outcome. invalid_links . iter ( ) {
107+ match & link. reason {
108+ Reason :: FileNotFound | Reason :: TraversesParentDirectories => {
109+ is_real_error = true ;
110+ }
111+ Reason :: UnsuccessfulServerResponse ( status) => {
112+ if status. is_client_error ( ) {
113+ is_real_error = true ;
114+ } else {
115+ eprintln ! ( "Unsuccessful server response for link `{}`" , link. link. uri) ;
116+ }
117+ }
118+ Reason :: Client ( err) => {
119+ if err. is_timeout ( ) {
120+ eprintln ! ( "Timeout for link `{}`" , link. link. uri) ;
121+ } else if err. is_server_error ( ) {
122+ eprintln ! ( "Server error for link `{}`" , link. link. uri) ;
123+ } else {
124+ is_real_error = true ;
125+ }
126+ }
127+ }
128+ }
129+
130+ if is_real_error {
131+ Ok ( ( outcome. generate_diagnostics ( & files, linkck_cfg. warning_policy ) , files) )
132+ } else {
133+ Ok ( ( vec ! [ ] , files) )
134+ }
84135}
85136
86137// Build command implementation
0 commit comments