@@ -31,6 +31,7 @@ use crate::formats::FormatRenderer;
3131use crate :: html:: escape:: Escape ;
3232use crate :: html:: format:: { join_with_double_colon, Buffer } ;
3333use crate :: html:: markdown:: { self , plain_text_summary, ErrorCodes , IdMap } ;
34+ use crate :: html:: url_parts_builder:: UrlPartsBuilder ;
3435use crate :: html:: { layout, sources} ;
3536use crate :: scrape_examples:: AllCallLocations ;
3637use crate :: try_err;
@@ -370,6 +371,35 @@ impl<'tcx> Context<'tcx> {
370371 anchor = anchor
371372 ) )
372373 }
374+
375+ pub ( crate ) fn href_from_span_relative (
376+ & self ,
377+ span : clean:: Span ,
378+ relative_to : & str ,
379+ ) -> Option < String > {
380+ self . href_from_span ( span, false ) . map ( |s| {
381+ let mut url = UrlPartsBuilder :: new ( ) ;
382+ let mut dest_href_parts = s. split ( '/' ) ;
383+ let mut cur_href_parts = relative_to. split ( '/' ) ;
384+ for ( cur_href_part, dest_href_part) in ( & mut cur_href_parts) . zip ( & mut dest_href_parts) {
385+ if cur_href_part != dest_href_part {
386+ url. push ( dest_href_part) ;
387+ break ;
388+ }
389+ }
390+ for dest_href_part in dest_href_parts {
391+ url. push ( dest_href_part) ;
392+ }
393+ let loline = span. lo ( self . sess ( ) ) . line ;
394+ let hiline = span. hi ( self . sess ( ) ) . line ;
395+ format ! (
396+ "{}{}#{}" ,
397+ "../" . repeat( cur_href_parts. count( ) ) ,
398+ url. finish( ) ,
399+ if loline == hiline { loline. to_string( ) } else { format!( "{loline}-{hiline}" ) }
400+ )
401+ } )
402+ }
373403}
374404
375405/// Generates the documentation for `crate` into the directory `dst`
0 commit comments