11use mdbook:: book:: Chapter ;
22use once_cell:: sync:: Lazy ;
33use regex:: { Captures , Regex } ;
4+ use std:: collections:: HashSet ;
45use std:: fmt:: Write as _;
56use std:: fs;
67use std:: io:: { self , Write as _} ;
@@ -32,6 +33,15 @@ static STD_LINK_RE: Lazy<Regex> = Lazy::new(|| {
3233static STD_LINK_EXTRACT_RE : Lazy < Regex > =
3334 Lazy :: new ( || Regex :: new ( r#"<li><a [^>]*href="(https://doc.rust-lang.org/[^"]+)""# ) . unwrap ( ) ) ;
3435
36+ /// The Regex for a markdown link definition.
37+ static LINK_DEF_RE : Lazy < Regex > = Lazy :: new ( || {
38+ // This is a pretty lousy regex for a link definition. It doesn't
39+ // handle things like blockquotes, code blocks, etc. Using a
40+ // markdown parser isn't really feasible here, it would be nice to
41+ // improve this.
42+ Regex :: new ( r#"(?m)^(?<label>\[[^]]+\]): *(?<dest>.*)"# ) . unwrap ( )
43+ } ) ;
44+
3545/// Converts links to the standard library to the online documentation in a
3646/// fashion similar to rustdoc intra-doc links.
3747pub fn std_links ( chapter : & Chapter ) -> String {
@@ -87,7 +97,7 @@ pub fn std_links(chapter: &Chapter) -> String {
8797 output
8898}
8999
90- /// Collects all markdown links.
100+ /// Collects all markdown links, excluding those that already have link definitions .
91101///
92102/// Returns a `Vec` of `(link, Option<dest>)` where markdown text like
93103/// ``[`std::fmt`]`` would return that as a link. The dest is optional, for
@@ -112,6 +122,21 @@ fn collect_markdown_links(chapter: &Chapter) -> Vec<(&str, Option<&str>)> {
112122 }
113123 links. sort ( ) ;
114124 links. dedup ( ) ;
125+ // Remove any links that already have a link definition. We don't want
126+ // to override what the author explicitly specified.
127+ let existing_labels: HashSet < _ > = LINK_DEF_RE
128+ . captures_iter ( & chapter. content )
129+ . map ( |cap| cap. get ( 1 ) . unwrap ( ) . as_str ( ) )
130+ . collect ( ) ;
131+ links. retain ( |( link, dest) | {
132+ let mut tmp = None ;
133+ let label: & str = dest. map_or ( link, |d| {
134+ tmp = Some ( format ! ( "[`{d}`]" ) ) ;
135+ tmp. as_deref ( ) . unwrap ( )
136+ } ) ;
137+ !existing_labels. contains ( label)
138+ } ) ;
139+
115140 links
116141}
117142
0 commit comments